什么是指標
我們都知道,程式運行時的資料是存放在記憶體中的,每一個存盤在記憶體中的資料都有一個編號,這個編號就是記憶體地址,我們可以根據這個記憶體地址來找到記憶體中存盤的資料,而記憶體地址可以被賦值給一個指標,我們也可以簡單的理解為指標就是記憶體地址,
指標的宣告和定義
在Go語言中,獲取一個指標,直接使用取地址符&就可以,
示例:
func main() {
name := "微客鳥窩"
nameP := &name //取地址
fmt.Println("name變數值為:", name)
fmt.Println("name變數的記憶體地址為:", nameP)
}
//運行結果:
//name變數值為: 微客鳥窩
//name變數的記憶體地址為: 0xc00004e240
- nameP 指標的型別是 *string
- Go語言中,
*型別名表示一個對應的指標型別
| 變數 | 記憶體中資料 | 記憶體地址 |
|---|---|---|
| name := "微客鳥窩" | 微客鳥窩 | 0xc00004e240 |
| nameP := &name | 0xc00004e240 | 0xc00004e360 |
從上面表格可以看到:
- 普通變數 name 的值是微客鳥窩,存放在記憶體地址為 0xc00004e240 的記憶體中
- 指標變數 namep 的值是普通變數的記憶體地址 0xc00004e240
- 指標變數 nameP 的值存放在 記憶體地址為 0xc00004e360 的記憶體中
- 普通變數存的是資料,指標變數存的是資料的地址
var 關鍵字宣告
我們也可以使用 var 關鍵字宣告
var nameP *string
nameP = &name
new 函式宣告
nameP := new(string)
nameP = &name
可以傳遞型別給這個內置的 new 函式,它會回傳對應的指標型別,
指標的操作
這里強調一下:
指標變數是一個變數,這個變數的值是指標(記憶體地址)!
指標變數是一個變數,這個變數的值是指標(記憶體地址)!
指標變數是一個變數,這個變數的值是指標(記憶體地址)!
- 獲取指標指向的值:
只需要在指標變數錢加*號即可獲得指標變數值所對應的資料:
nameV := *nameP
fmt.Println("nameP指標指向的值為:",nameV) //nameP指標指向的值為: 微客鳥窩
- 修改指標指向的值:
*nameP = "公眾號:微客鳥窩" //修改指標指向的值
fmt.Println("nameP指標指向的值為:",*nameP)
fmt.Println("name變數的值為:",name)
//運行結果:
//nameP指標指向的值為: 公眾號:微客鳥窩
//name變數的值為: 公眾號:微客鳥窩
- 我們發現nameP 指標指向的值被改變了,變數 name 的值也被改變了
- 因為變數 name 存盤資料的記憶體就是指標 nameP 指向的記憶體,這塊記憶體被 nameP 修改后,變數 name 的值也被修改了,
- 通過 var 關鍵字直接定義的指標變數是不能進行賦值操作的,因為它的值為 nil,也就是還沒有指向的記憶體地址
//錯誤示例
var intP *int
*intP = 10 //錯誤,應該先給分配一塊記憶體,記憶體地址作為變數 intP 的值,這個記憶體就可以存放 10 了,
//應該使用
var intP *int //宣告int型別的指標變數 intP
intP = new(int) // 給指標分配一塊記憶體
*intP = 66
fmt.Println(":::",intP) //::: 0xc0000ac088
fmt.Println(*intP) //66
//簡短寫法
var intP := new(int)
*intP=66
指標引數
當給一個函式使用指標作為引數的時候,就可以在函式中,通過形參改變實參的值:
func main() {
name := "無塵"
modify(&name)
fmt.Println("name的值為:",name)
}
func modify(name *string) {
*name = "wucs"
}
//運行結果:
//name的值為: wucs
指標接收者
- 如果接收者型別是 map、slice、channel 這類參考型別,不使用指標;
- 如果需要修改接收者,那么需要使用指標;
- 如果接收者是比較大的型別,可以考慮使用指標,因為記憶體拷貝廉價,所以效率高,
什么情況下使用指標
- 不要對 map、slice、channel 這類參考型別使用指標;
- 如果需要修改方法接收者內部的資料或者狀態時,需要使用指標;
- 如果需要修改引數的值或者內部資料時,也需要使用指標型別的引數;
- 如果是比較大的結構體,每次引數傳遞或者呼叫方法都要記憶體拷貝,記憶體占用多,這時候可以考慮使用指標;
- 像 int、bool 這樣的小資料型別沒必要使用指標;
- 如果需要并發安全,則盡可能地不要使用指標,使用指標一定要保證并發安全;
- 指標最好不要嵌套,也就是不要使用一個指向指標的指標,雖然 Go 語言允許這么做,但是這會使你的代碼變得例外復雜,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/295963.html
標籤:Go
