为什么比较两个指向结构体的变量在Golang中的行为不同?

huangapple go评论71阅读模式
英文:

golang why comparing two variables pointing to struct behaves differently?

问题

我已经创建了两个相同结构的实例,当我比较指向结构实例的两个变量时,输出让我感到困惑。

package main

import "fmt"

type Person struct {
    name string
}

func main() {
    p1 := &Person{name: "guru"}
    p2 := &Person{name: "guru"}
    fmt.Println(p1 == p2) // false,通过地址进行比较?
    p3 := Person{name: "guru"}
    p4 := Person{name: "guru"}
    fmt.Println(p3 == p4) // true,为什么?通过内容进行比较?
}

== 运算符是否像重载运算符一样工作?

英文:

I have created two instances of same struct, Confused by the output when I compare two variables point to instances of struct.

package main

import "fmt"

type Person struct {
    name string
}

func main() {
   p1 := &Person{name: "guru"}
   p2 := &Person{name: "guru"}
   fmt.Println(p1 == p2) // false, compares by address?
   p3 := Person{name: "guru"}
   p4 := Person{name: "guru"}
   fmt.Println(p3 == p4) // true , why? compares by content?
}

does == operator works like overload operator?

答案1

得分: 8

p1 == p2 是指针比较,它比较指针的值(内存地址)。由于您使用了两个复合字面量(并且取了它们的地址),它们将指向两个不同的变量,因此地址将不同(因为Person的大小不为零)。规范:复合字面量

> 取复合字面量的地址会生成一个指向使用该字面量的值初始化的唯一变量的指针。

p3 == p4 比较结构体的值,它逐个字段进行比较,由于匹配的字段具有相等的值,比较结果将为true

比较规则在规范:比较运算符中定义:

> 等号运算符==和!=适用于可比较的操作数。小于号<、小于等于号<=、大于号>和大于等于号>=适用于有序的操作数。这些术语和比较的结果定义如下:
> - [...]
> - 指针值是可比较的。如果两个指针值指向同一个变量或者都具有值nil,则它们相等。指向不同的零大小变量的指针可能相等,也可能不相等。
> - [...]
> - 如果结构体的所有字段都是可比较的,则结构体值是可比较的。如果两个结构体值的对应非空白字段相等,则它们相等。

英文:

p1 == p2 is pointer comparison, it compares the pointer values (the memory addresses). Since you used 2 composite literals (and took their addresses), they will point to 2 distinct variables, so the addresses will be different (since size of Person is not zero). Spec: Composite literals:

> Taking the address of a composite literal generates a pointer to a unique variable initialized with the literal's value.

p3 == p4 compares struct values, it compares them field-by-field, and since the matching fields have equal values, the comparison will result in true.

Comparison rules are in Spec: Comparison operators:

> The equality operators == and != apply to operands that are comparable. The ordering operators <, <=, >, and >= apply to operands that are ordered. These terms and the result of the comparisons are defined as follows:
> - [...]
> - Pointer values are comparable. Two pointer values are equal if they point to the same variable or if both have value nil. Pointers to distinct zero-size variables may or may not be equal.
> - [...]
> - Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.

答案2

得分: 4

你的第一个例子比较了两个指针的相等性。由于它们分别指向不同的内存地址,所以它们不相等。

你的第二个例子比较了两个结构体的值,因此它们相等。

如果在比较之前对指针进行解引用,你会发现它们相等。例如,给定以下代码:

p1 := &Person{name: "guru"}
p2 := &Person{name: "guru"}
p3 := Person{name: "guru"}
p4 := Person{name: "guru"}

以下所有比较都相等:

  • *p1 == *p2
  • *p1 == p3
  • p3 == *p2
  • p3 == p4
英文:

Your first example
>
&gt; p1 := &amp;Person{name: &quot;guru&quot;}
&gt; p2 := &amp;Person{name: &quot;guru&quot;}
&gt;
&gt; fmt.Println(p1 == p2) // false, compares by address?
&gt;

compares two pointers for equality. Since they each address different memory addresses, the do not compare as equal.

Your second example,
>
&gt; p3 := Person{name: &quot;guru&quot;}
&gt; p4 := Person{name: &quot;guru&quot;}
&gt;
&gt; fmt.Println(p3 == p4) // true , why? compares by content?
&gt;

compares two struct and does so by value, so they compare equal.

If you dereference the pointer before the comparison, you'll find that they compare as equal. For instance, given

p1 := &amp;Person{ name: &quot;guru&quot; }
p2 := &amp;Person{ name: &quot;guru&quot; }
p3 :=  Person{ name: &quot;guru&quot; }
p4 :=  Person{ name: &quot;guru&quot; }

All of the following compare as equal:

  • *p1 == *p2
  • *p1 == p3
  • p3 == *p2
  • p3 == p4

答案3

得分: 1

两个指针的值只有在它们指向内存中的相同值时才相等,或者在Golang中它们都是nil时才相等。
你创建了两个结构体实例,因此它们具有不同的地址。

p1 := &Person{name: "guru"}
p2 := &Person{name: "guru"}

英文:

Two pointers values are only equal when they point to the same value in the memory or if they are nil in Golang.
You create two instances of struct, thus they have different address

   p1 := &amp;Person{name: &quot;guru&quot;}
   p2 := &amp;Person{name: &quot;guru&quot;}

huangapple
  • 本文由 发表于 2022年2月10日 01:30:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/71054114.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定