[英]GoLang pointers are behaving wierd
为什么更改 node2.Next 会影响下面代码中的 node2?
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
func main() {
node1 := ListNode{Val:10 , Next:nil}
node2 := ListNode{Val:100 , Next:&node1}
temp := node2
if(temp == node2){
fmt.Println("Equalssss1")
}
node2.Next = &(ListNode{1 , nil})
if(temp == node2){
fmt.Println("Equalssss2")
}
}
基本上为什么不打印“Equalsss2”? 我感觉既然改了node2.Next但没改node2,node2应该等于temp 为什么不是呢?
您的代码中没有行为不当的指针。 我怀疑你认为的指针实际上并不是指针,因此你很困惑。
在您的代码中, node1
和node2
是ListNode
结构,即 _ value types 。 当您将node2
分配给temp
时, temp
会保存node2
的副本,而不是指向它的指针或引用。
在 Go 中,(简单来说)如果两个结构值具有相同的类型并且由可比较的字段组成且都被评估为相等,则它们是相等的。
当您最初比较node2
和temp
时,这两个值中每个值的所有字段的值都相同,因此temp == node2
的计算结果为真。
然后更改node2
的Next
字段,因此当您再次比较temp == node2
时,它们不再相等,因为它们在该字段的值上不同。
要获得您期望的行为, node1
和node2
需要是指向ListNode
的指针:
type ListNode struct {
Val int
Next *ListNode
}
func main() {
node1 := &ListNode{Val: 10, Next: nil}
node2 := &ListNode{Val: 100, Next: node1}
temp := node2
if temp == node2 {
fmt.Println("Equalssss1")
}
node2.Next = &(ListNode{1, nil})
if temp == node2 {
fmt.Println("Equalssss2")
}
}
temp
现在也是指向ListNode
的指针,而不是ListNode
值的副本; temp
被初始化为引用node2
引用的同一个ListNode
。 即指针temp
和node2
相等; 他们都指向同一个ListNode
。
现在,当您更改node2.Next
时,这不会影响temp
仍然只是node2
指针的副本这一事实,并且由于node2
本身(指针)和temp
的值都没有改变,它们仍然相等。
即,如果您使用指针,您的代码将按预期运行。 如果您认为指针表现得“怪异”,那是因为在这种情况下,您实际上并没有使用指针。 :)
正如您问题的评论者试图指出的那样,这里没有发生任何奇怪的事情。 在您的第一个条件之后添加:
fmt.Printf("temp is at %p and temp.Next is at %p\nnode2 is at %p and node2.Next is at %p\n", &temp, temp.Next, &node2, node2.Next)
这将是 output:
temp is at 0xc00009e240 and temp.Next is at 0xc00009e220
node2 is at 0xc00009e230 and node2.Next is at 0xc00009e220
并尝试在第二个条件之后添加此行:
fmt.Printf("temp.Next has Val: %d\nnode2.Next has Val: %d\n", temp.Next.Val, node2.Next.Val)
这将是 output:
temp.Next has Val: 10
node2.Next has Val: 1
你可以在这里看到结果。
node2
和temp
指向不同的对象,在您修改node.Next
之前,这两个对象具有相同的字段值。 您的分配temp:= node2
make 创建了结构类型的新实例,并复制了源 object 中的值。它不会创建指向node
object 的指针 - 如果有,则更改node2.<field>
也会更改temp.<field>
。 这有点令人困惑,因为在 go 中(与 C 不同)您不需要取消引用指针/使用不同的访问器语法来访问结构字段,因此以下内容完全没问题:
temp := &node2
node2.Val = 500
fmt.Printf("%d == %d\n, temp.Val, node2.Val)
最终,这里的一切都如人们所想的那样发生着。 换句话说,您的第一个条件是检查相等性而不是身份。 具有相同值(平等)的不同对象(身份)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.