关于Golang中Defer结合指针的代码运行结果的疑问
为什么这段Go代码的运行结果是这样?
代码示例
package main import ( "fmt" ) type userinfo struct { id int } func main() { user := new(userinfo) user = nil fmt.Println("nil user address : ", &user) defer Println(user) if user == nil { user = &userinfo{ id: 1, } fmt.Println("nil user point new user:", &user) } } func Println(user *userinfo) { fmt.Println("defer: ", &user) fmt.Println("defer:", user) }
运行结果
nil user address : 0xc00000e028 nil user point new user: 0xc00000e028 defer: 0xc00000e038 defer: <nil>
结果解释
- 变量
user自身的地址固定不变:user是main函数的局部变量,存储在栈上,它的内存地址(&user)从声明到销毁都不会改变。不管user的值(也就是它指向的结构体指针)怎么修改,它自己的地址始终是同一个,所以前两行输出的地址完全一致。 - defer语句的参数在声明时就完成求值:当执行
defer Println(user)时,Go会立即计算出此时user的值(也就是nil)并保存,后续即使修改user的指向(给它赋值新的userinfo结构体指针),也不会影响已经保存的defer参数值。所以最后Println函数接收到的参数还是nil。 - Println函数的形参是独立的局部变量:
Println里的user是函数参数,是main中user的副本,它有自己的栈内存地址,所以&user的输出和main里的&user不一样,这就是第三行输出地址不同的原因。
内容的提问来源于stack exchange,提问作者Aa troy
相关产品推荐
相关产品推荐

