Go 語(yǔ)言中的值類型和指針類型區(qū)別對(duì)比分析
在 Go 語(yǔ)言中,變量的類型可以是值類型(Value Type)或指針類型(Pointer Type)。它們的核心區(qū)別在于:存儲(chǔ)的內(nèi)容不同、內(nèi)存地址的變化不同、函數(shù)傳參的行為不同。
下面我從本質(zhì) + 內(nèi)存模型 + 例子 + 什么時(shí)候用指針 來完整解釋。
? 一、值類型 vs 指針類型 — 本質(zhì)區(qū)別
| 特性 | 值類型 | 指針類型 |
|---|---|---|
| 存儲(chǔ)內(nèi)容 | 實(shí)際數(shù)據(jù) | 數(shù)據(jù)的內(nèi)存地址(指向某個(gè)值) |
| 賦值時(shí) | 拷貝整份數(shù)據(jù) | 拷貝地址(兩個(gè)指針指向同一塊內(nèi)存) |
| 改動(dòng)是否影響原變量 | ? 不影響 | ? 會(huì)影響 |
| 空值 | 無法為 nil | 可以為 nil |
| 內(nèi)存分配 | 棧為主 | 指向堆或棧都可能 |
? 二、本質(zhì)理解:變量保存的是什么?
? 值類型(int、float、struct、array 等)
變量里保存的是“真實(shí)的數(shù)據(jù)”。
a := 10 b := a // b 拷貝一份 10 b = 20 fmt.Println(a) // 10 (不會(huì)受到影響)
值類型總是復(fù)制一份獨(dú)立的數(shù)據(jù)。
? 指針類型(*int、*struct、*MyType)
變量里保存的是“另一個(gè)變量的地址”。
a := 10 b := &a // b 保存 a 的地址 *b = 20 fmt.Println(a) // 20 (a 被修改)
指針類型意味著多個(gè)變量指向同一塊內(nèi)存,因此修改一個(gè)會(huì)影響另一個(gè)。
? 三、內(nèi)存示意圖(最直觀)
? 值類型
a (10) b (10) ← 拷貝出的新數(shù)據(jù)
? 指針類型
a (10) b (&a) → 指向 a 的內(nèi)存地址
? 四、函數(shù)傳參時(shí)的區(qū)別(非常重要)
值類型:傳值,拷貝一份
func add(x int) {
x++
}
a := 10
add(a)
fmt.Println(a) // 10(沒有改變)指針類型:傳地址,修改原變量
func add(x *int) {
(*x)++
}
a := 10
add(&a)
fmt.Println(a) // 11(被改變了)? 五、結(jié)構(gòu)體特別重要:值類型默認(rèn)復(fù)制!
type User struct {
Name string
}
func change(u User) {
u.Name = "Tom"
}
func main() {
user := User{Name: "Sam"}
change(user)
fmt.Println(user.Name) // Sam(沒變)
}改用指針就會(huì)改變?cè)瓟?shù)據(jù):
func change(u *User) {
u.Name = "Tom"
}
change(&user)
fmt.Println(user.Name) // Tom? 六、什么時(shí)候應(yīng)該使用指針?
? 1. 需要修改函數(shù)外的變量
修改狀態(tài)、計(jì)數(shù)器、累加器等。
? 2. struct 較大,避免復(fù)制(性能)
Go 的結(jié)構(gòu)體可能很大,復(fù)制成本高:
func process(u *LargeStruct) { ... }? 3. 實(shí)現(xiàn)方法的“接收者”為指針(避免復(fù)制)
很多類型的方法必須用指針接收器:
func (u *User) SetName(name string) {
u.Name = name
}? 4. 需要表示 nil(值不存在)
var p *User = nil
值類型永遠(yuǎn)不能為 nil。
? 七、一句話總結(jié)
- 值類型保存真實(shí)值,賦值會(huì)復(fù)制,不會(huì)影響彼此。
- 指針類型保存地址,賦值只復(fù)制地址,多個(gè)變量共享底層數(shù)據(jù)。
- 指針多用于需要改變?cè)瓟?shù)據(jù)、避免拷貝大結(jié)構(gòu)體、或表示 nil 的場(chǎng)景。
到此這篇關(guān)于Go 語(yǔ)言中的值類型和指針類型的文章就介紹到這了,更多相關(guān)go語(yǔ)言值類型和指針類型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang函數(shù)重試機(jī)制實(shí)現(xiàn)代碼
在編寫應(yīng)用程序時(shí),有時(shí)候會(huì)遇到一些短暫的錯(cuò)誤,例如網(wǎng)絡(luò)請(qǐng)求、服務(wù)鏈接終端失敗等,這些錯(cuò)誤可能導(dǎo)致函數(shù)執(zhí)行失敗,這篇文章主要介紹了Golang函數(shù)重試機(jī)制實(shí)現(xiàn)代碼,需要的朋友可以參考下2024-04-04
Goland遠(yuǎn)程連接Linux進(jìn)行項(xiàng)目開發(fā)的實(shí)現(xiàn)
有的時(shí)候我們的開發(fā)代碼要在linux服務(wù)器上運(yùn)行,本文主要介紹了Goland遠(yuǎn)程連接Linux進(jìn)行項(xiàng)目開發(fā)的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06
go?goroutine實(shí)現(xiàn)素?cái)?shù)統(tǒng)計(jì)的示例
這篇文章主要介紹了go?goroutine實(shí)現(xiàn)素?cái)?shù)統(tǒng)計(jì),本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07
使用gopacket解析協(xié)議層中的相關(guān)數(shù)據(jù)方式
文章介紹使用Wireshark抓取ping數(shù)據(jù)包并保存為pcap格式,通過Go語(yǔ)言gopacket解析,提取IP版本號(hào)、指定標(biāo)識(shí)的數(shù)據(jù)包長(zhǎng)度及應(yīng)用層ICMP字符串內(nèi)容,展示TCP/IP協(xié)議族解析的簡(jiǎn)便方法2025-07-07
Go語(yǔ)言實(shí)現(xiàn)Snowflake雪花算法
雪花算法產(chǎn)生的背景當(dāng)然是twitter高并發(fā)環(huán)境下對(duì)唯一ID生成的需求,得益于twitter內(nèi)部牛的技術(shù),雪花算法能夠流傳于至今并且被廣泛使用,本文就詳細(xì)的介紹一下,感興趣的可以了解一下2021-06-06
使用?gomonkey?Mock?函數(shù)及方法示例詳解
在 Golang 語(yǔ)言中,寫單元測(cè)試的時(shí)候,不可避免的會(huì)涉及到對(duì)其他函數(shù)及方法的 Mock,即在假設(shè)其他函數(shù)及方法響應(yīng)預(yù)期結(jié)果的同時(shí),校驗(yàn)被測(cè)函數(shù)的響應(yīng)是否符合預(yù)期,這篇文章主要介紹了使用?gomonkey?Mock?函數(shù)及方法,需要的朋友可以參考下2022-06-06
Golang defer延遲語(yǔ)句的實(shí)現(xiàn)
defer擁有注冊(cè)延遲調(diào)用的機(jī)制,本文主要介紹了Golang defer延遲語(yǔ)句的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07

