簡體   English   中英

GoLang 指針表現得很奇怪

[英]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 為什么不是呢?

您的代碼中沒有行為不當的指針。 我懷疑你認為的指針實際上並不是指針,因此你很困惑。

在您的代碼中, node1node2ListNode結構,即 _ value types 當您將node2分配給temp時, temp會保存node2副本而不是指向它的指針或引用。

在 Go 中,(簡單來說)如果兩個結構值具有相同的類型並且由可比較的字段組成且都被評估為相等,則它們是相等的。

當您最初比較node2temp時,這兩個值中每個值的所有字段的值都相同,因此temp == node2的計算結果為真。

然后更改node2Next字段,因此當您再次比較temp == node2時,它們不再相等,因為它們在該字段的值上不同。

要獲得您期望的行為, node1node2需要是指向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 即指針tempnode2相等; 他們都指向同一個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

你可以在這里看到結果。

node2temp指向不同的對象,在您修改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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM