golang 为什么命名和非命名结构比较结果相同

标签 go struct types comparison

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 个规范,它就是可比较的:

  1. Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.

  2. In any comparison, the first operand must be assignable to the type of the second operand, or vice versa.

第一个是特定于结构类型变量的;第二个是所有类型的变量比较,当然包括struct类型变量。

在我的示例中,比较变量 v1 和 v3 满足这两个规范定义。

  1. 所有领域都具有可比性;事实上,第一个规范定义了结构规则,它关注字段,而不是结构本身,所以无论是命名结构还是匿名结构,它们都是相同的规则。
  2. 变量 v1 和 v3 是可赋值的。 (根据规则:x 的类型 V 和 T 具有相同的底层类型,并且 V 或 T 中至少有一个不是定义类型)

所以这是为了解释为什么“v1 == v3”可以得到一个真正的结果。 谢谢大家。

最佳答案

如果仔细阅读该规范,您会发现如果相应的非空白字段相等,则两个结构相等。如果类型 name 不同,编译器将失败,但如果其中一个或两个类型是匿名的,那么它们将是可比较的。 T1T2 类型和匿名结构实际上是同一类型,因为它们具有相同的字段。当字段值相同时,它们比较相同。

查看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/

相关文章:

c++ - 从循环添加到结构 (c++)

c - 在函数的返回语句中创建的结构体数据可在调用函数中使用

c - 试图在 C 中打印一个结构数组

Java 泛型扩展仍然会生成未经检查的强制转换警告

json - 打印 POST JSON 数据

json - 在 Go 中的 json.Marshal 期间锁定对象

http - go语言如何通过http请求下载文件

Golang Gin "c.Param undefined (type *gin.Context has no field or method Param)"

c++ - short(expression) 是什么意思?

java - 如何在 Java 中使用数组进行类型泛型?