// 记录一下学习指针时遇到的问题,如表述或理解有误,欢迎指正.
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也发生了变化.