Go 编程语言 Specification说。
Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.
但如下代码片段,变量v1和v3的类型似乎不同,为什么它们能得到真正的输出:
package main
import "fmt"
import "reflect"
type T1 struct { name string }
type T2 struct { name string }
func main() {
v1 := T1 { "foo" }
v2 := T2 { "foo" }
v3 := struct{ name string } {"foo"}
v4 := struct{ name string } {"foo"}
fmt.Println("v1: type=", reflect.TypeOf(v1), "value=", reflect.ValueOf(v1)) // v1: type= main.T1 value= {foo}
fmt.Println("v2: type=", reflect.TypeOf(v2), "value=", reflect.ValueOf(v2)) // v2: type= main.T2 value= {foo}
fmt.Println("v3: type=", reflect.TypeOf(v3), "value=", reflect.ValueOf(v3)) // v3: type= struct { name string } value= {foo}
fmt.Println("v4: type=", reflect.TypeOf(v4), "value=", reflect.ValueOf(v4)) // v4: type= struct { name string } value= {foo}
//fmt.Println(v1 == v2) // compiler error: invalid operation: v1 == v2 (mismatched types T1 and T2)
fmt.Println(v1 == v3) // true, why? their type is different
fmt.Println(v2 == v3) // true, why?
fmt.Println(v3 == v4) // true
}
v1 == v2
因编译错误而失败是合理的,因为它们是不同的类型,但是如何解释 v1 == v3
得到一个 true
结果,因为它们也有不同的类型,一个是命名结构类型 T1
,另一个是匿名结构。
谢谢。
根据反馈更新问题
感谢@icza、@John Weldon 的解释,我认为这个问题已经解决,我现在正在更新问题。
总而言之,如果一个结构满足以下 2 个规范,它就是可比较的:
Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.
In any comparison, the first operand must be assignable to the type of the second operand, or vice versa.
第一个是特定于结构类型变量的;第二个是所有类型的变量比较,当然包括struct类型变量。
在我的示例中,比较变量 v1 和 v3 满足这两个规范定义。
- 所有领域都具有可比性;事实上,第一个规范定义了结构规则,它关注字段,而不是结构本身,所以无论是命名结构还是匿名结构,它们都是相同的规则。
- 变量 v1 和 v3 是可赋值的。 (根据规则:x 的类型 V 和 T 具有相同的底层类型,并且 V 或 T 中至少有一个不是定义类型)
所以这是为了解释为什么“v1 == v3”可以得到一个真正的结果。 谢谢大家。
最佳答案
如果仔细阅读该规范,您会发现如果相应的非空白字段相等,则两个结构相等。如果类型 name 不同,编译器将失败,但如果其中一个或两个类型是匿名的,那么它们将是可比较的。 T1
或 T2
类型和匿名结构实际上是同一类型,因为它们具有相同的字段。当字段值相同时,它们比较相同。
查看type identity在规范中可能(或可能不会,ymmv)使其更清晰。
Two struct types are identical if they have the same sequence of fields, and if corresponding fields have the same names, and identical types, and identical tags. Non-exported field names from different packages are always different.
因此,如果您尝试相同的实验但通过添加字段标记或将类型放在不同的包中来更改类型,您可能会得到预期的差异。
关于golang 为什么命名和非命名结构比较结果相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46679484/