// 記錄一下學習指針時遇到的問題,如表述或理解有誤,歡迎指正.
1.指針變量是用來存放內存地址的變量,它的值是一個內存地址,而它本身也保存在一個內存地址中.
2.當初始化一個指針變量時,cpu會開辟一塊內存給這個指針變量;當給這個指針變量賦值后,這個指針會指向一個地址,其值為申明變量時指定類型的零值.
func main() {
var myInt *int //申明一個指針變量myInt
fmt.Println(&myInt, myInt) //0xc000006028 <nil> 開辟一塊地址給指針變量,初始化前的值為nil
myInt = new(int) //初始化myInt
fmt.Println(&myInt, myInt, *myInt) //0xc000006028 0xc00000a0c8 0 初始化后myInt指向被分配的地址,值為類型的零值
t := 1 //申明一個int類型變量
fmt.Println(&t) //0xc00000a100 int類型變量的地址
*myInt = t // 將t的值賦值給*myInt,此時myInt指向的地址並沒有發生變化
fmt.Println(&myInt, myInt, *myInt) //0xc000006028 0xc00000a0c8 1 myInt指向的地址沒有發生變化,但那個地址對應的值以及被修改為1
myInt = &t //將t的地址賦值給muInt,此時myInt指向的地址發生變化
fmt.Println(&myInt, myInt, *myInt) //0xc000006028 0xc00000a100 1 myInt指向的地址已經不是初始化時cpu分配的地址,而是變成變量t的地址,對應的值也變成t的值
}
myInt = &t這種操作會修改myInt初始化時指向的地址,所以在開發時會存在下邊的坑:
案例:
func Test(s *string) error {
fmt.Println(s) //s的地址為: 0xc000046230
myTest := "hello world"
s = &myTest
fmt.Println(s) //s的地址為: 0xc000046240
return nil
}
func main() {
var str string
_ = Test(&str)
fmt.Println(str)
}
/*
上段代碼中,Test函數接收一個指針變量類型的參數,即str變量對應的內存地址;
在函數中申明了一個string類型的變量,當執行s=&myTest時,指針變量s指向的地址由&str變成了&myTest;
此時*s的值為"hello world",但並未對&str做任何修改,相當於&str傳進來馬上就被替換掉了;
&str並未做任何改變,所以最后在主函數中打印str時發現它為空
*/
處理:
func Test(s *string) error {
fmt.Println(s) //s的地址為: 0xc000088220
myTest := "hello world"
*s = myTest
fmt.Println(s) //s的地址為: 0xc000088220
return nil
}
func main() {
var str string
_ = Test(&str)
fmt.Println(str) //hello world
}
/*
當使用*s = myTest這種方式進行賦值時,相當於將s指向的地址對應的值修改為"hello world", 即在函數Test中地址&str對應的值被修改
所以在最后打印時成功修改str
*/
總結:
對於*s = myTest和s = &myTest這兩種操作,*s的最終值雖然都是"hello world",但是在計算機內部卻是不同的:
*s = myTest相當於修改s指針變量指向地址對應的值,指向的地址未發生變化;
s = &myTest相當於修改了指針變量s指向的地址,相應的*s也發生了變化.
