泻药

这种小题目有点意思,不注意便很容易犯错,我也不例外。

将题主的代码改写一下:

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天学习之后,平时做项目体会的。