泻药
这种小题目有点意思,不注意便很容易犯错,我也不例外。
将题主的代码改写一下:
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
func main() {
l1 := ListNode{0,nil}
l1.Val = 1
next := ListNode{0,nil}
next.Val = 2
fmt.Printf("%p\n", &next)
l1.Next = &next
next = ListNode{0,nil}
fmt.Printf("%p\n", &next)
ptr := l1.Next
fmt.Println(ptr.Val)
}
输出:
0xc42000e1d0
0xc42000e1d0
0
这表明变量next的内存地址并没有变化,上例中均是指向“0xc42000e1d0”。地址没有变化,自然改变其Val值为0后,输出的也是0。
这一行代码,在原代码中是多余的:
next = ListNode{0,nil}
结构体实例值传递,只改变成员值,不改变实例的引用地址。
像结构体这种对象的实例,最好都统一用new函数实例化,在变量里存储指针类型。将上面的代码改写一下:
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
func main() {
l1 := new(ListNode)
l1.Val = 1
next := new(ListNode)
next.Val = 2
fmt.Printf("%p\n", next)
l1.Next = next
// next = new(ListNode)
fmt.Printf("%p\n", next)
ptr := l1.Next
fmt.Println(ptr.Val)
}
输出:
0xc42000e1d0
0xc42000e1d0
2
这样,有没有倒数第4行代码都一样。
写多了,我都赚自己啰嗦了~
但这些东西才是一个语言的基本功,是在3天学习之后,平时做项目体会的。