关于golang中指针赋值的问题
目录
最近在SO上找到了一个很有意思的问题:SO
这个问题是关于一个指针在外部函数的赋值,当然,解决方法也很简单。
type userIP net.IP
func main() {
var u *userIP
u.defaultIP()
fmt.Printf("%v\n", u)
}
func (u *userIP) defaultIP() {
defaultIP := userIP("127.0.0.1")
u = &defaultIP
}
但是为什么会这样?如果是学过C风格指针的话应该会发现这条语句是很奇怪的,从语法上讲u中存放的地址会被改变,但是实际上它并不会改变(PS:原来的这个代码需要修改一下,不然会有dereference nil的错误)
修改后的例子
package main
import (
"fmt"
"net"
)
type userIP net.IP
func main() {
s:= userIP("123.2.2.1")
var u *userIP = &s
fmt.Printf("address of s %p\n",&s)
fmt.Printf("what's in u? u = %p, &u = %p\n",u,&u)
fmt.Println("In main function")
fmt.Printf("main(): address of pointer is %v, address inside pointer is %p\n", &u,u)
fmt.Printf("main(): user IP address is %s\n", *u)
u.defaultIP()
fmt.Println("After executing defaultIP")
fmt.Printf("main(): address of pointer is %v, address inside pointer is %p\n", &u,u)
fmt.Printf("main(): user IP address is %s\n", *u)
hyperIP(&u)
fmt.Println("After executing hyperIP")
fmt.Printf("main(): address of pointer is %v, address inside pointer is %p\n", &u,u)
fmt.Printf("main(): user IP address is %s\n", *u)
}
func (u *userIP) defaultIP() {
defaultIP := userIP("127.0.0.1")
u = &defaultIP
fmt.Println("In function defaultIP")
fmt.Printf("defaultIP(): address of pointer is %v, address inside pointer is %p\n", &u,u)
fmt.Printf("defaultIP(): user IP address is %s\n", *u)
}
func hyperIP(u **userIP) {
defaultIP := userIP("129.0.0.1")
*u = &defaultIP
fmt.Println("In function hyperIP")
fmt.Printf("hyperIP(): address of pointer is %v, address inside pointer is %p\n", &u,u)
fmt.Printf("hyperIP(): user IP address is %s\n", *u)
}
通过上面这个例子可以进一步揭示问题,输出结果如下:
address of s 0xc0000044c0
what's in u? u = 0xc0000044c0, &u = 0xc000006028
In main function
main(): address of pointer is 0xc000006028, address inside pointer is 0xc0000044c0
main(): user IP address is 123.2.2.1
In function defaultIP
defaultIP(): address of pointer is 0xc000006038, address inside pointer is 0xc000004520
defaultIP(): user IP address is 127.0.0.1
After executing defaultIP
main(): address of pointer is 0xc000006028, address inside pointer is 0xc0000044c0
main(): user IP address is 123.2.2.1
In function hyperIP
hyperIP(): address of pointer is 0xc000006040, address inside pointer is 0xc000006028
hyperIP(): user IP address is &129.0.0.1
After executing hyperIP
main(): address of pointer is 0xc000006028, address inside pointer is 0xc000004580
main(): user IP address is 129.0.0.1
可以看到,对于主函数中的指针u,其地址为0xc000006028,其存放的地址为0xc0000044c0,这个与声明的变量是一致的。 问题在于,传入函数中的指针的地址是变动的,也就是传入函数的指针并不是原来的指针(这很正常,因为golang并没有引用传值,每一个变量的地址都是不一样的)。
所以,单纯修改指针中存放的内容是没有任何用处的。如果假设指针是杯子,里面存放的内容是某种液体,现在main函数中的u杯子里面装的是水,那么defaultIP杯子中装的就是酱油。如果想要让main的u杯中也装入酱油,唯一的方法就是把酱油倒进u杯中,因为go不支持对两个杯子的替换。