struct{int}和struct{int int}有什么区别?

5
除了它们不被视为等同之外,这两个结构体有什么区别?
package main
import "fmt"
func main() {
    a := struct{int}{1}
    b := struct{int int}{1}
    fmt.Println(a,b)
    a.int=2
    b.int=a.int
    fmt.Println(a,b)
    //a = b
}

它们看起来一样:

$ go run a.go 
{1} {1}
{2} {2}

如果您取消注释a = b,它会显示:
$ go run a.go 
# command-line-arguments
./a.go:10: cannot use b (type struct { int int }) as type struct { int } in assignment

然而,struct{a,b int}struct{a int;b int}是等价的:

package main

func main() {
    a := struct{a,b int}{1,2}
    b := struct{a int;b int}{1,2}
    a = b
    b = a
}

?

1个回答

9
"struct { int }"是一个具有匿名类型为int的结构体。
"struct { int int }"是一个具有类型为int且命名为int的字段的结构体。 int不是一个关键字,可以作为标识符使用。
两个结构体类型不相同;对应的字段没有相同的名称。
声明一个带有类型但没有显式字段名称的字段是一个匿名字段,未限定的类型名称充当匿名字段名称。因此,字段名称a.intb.int是有效的。例如:
a := struct{ int }{1}
b := struct{ int int }{1}
a.int = 2
b.int = a.int

The Go Programming Language Specification

Struct types

A struct is a sequence of named elements, called fields, each of which has a name and a type. Field names may be specified explicitly (IdentifierList) or implicitly (AnonymousField). Within a struct, non-blank field names must be unique.

StructType     = "struct" "{" { FieldDecl ";" } "}" .
FieldDecl      = (IdentifierList Type | AnonymousField) [ Tag ] .
AnonymousField = [ "*" ] TypeName .

A field declared with a type but no explicit field name is an anonymous field, also called an embedded field or an embedding of the type in the struct. An embedded type must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type. The unqualified type name acts as the field name.

Keywords

The following keywords are reserved and may not be used as identifiers.

break        default      func         interface    select
case         defer        go           map          struct
chan         else         goto         package      switch
const        fallthrough  if           range        type
continue     for          import       return       var

Type identity

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. Two anonymous fields are considered to have the same name. Lower-case field names from different packages are always different.


字段名称不同?那么为什么a.intb.int都可以工作呢? - Dog
@Dog:对于匿名字段,未经限定的类型名称充当匿名字段名称。请参阅我的修订答案。 - peterSO
我认为这个想法是(如果我错了,请纠正我,@peterSO)虽然int可以用来访问字段,但它不是字段的名称,就像struct{ a int }中的a是字段的名称一样(因此不是类型相等的目的)。 - joshlf
1
@synful:是的,有两个问题。第一,这两种类型是否相同(完全相同)?类型标识规则适用;显式字段名称必须完全相同。第二,我们如何引用匿名字段?未限定的类型名称充当隐式字段名称。 - peterSO
你刚刚粘贴的内容似乎暗示了 struct{int}=struct{int int}。但我认为这里没有足够的信息来确定。无论哪种情况,我想知道这两种类型实际上有什么不同,除了编译器认为它们不同之外。 - Dog
@Dog:不,正如Go编程语言规范的类型标识规则明确指出的那样,struct { int }struct { int int }并不相同,它们并不完全相同。匿名字段(明确无名称)不能与显式命名字段具有完全相同的名称。按设计,Go编程语言简单、直观和正交。该规范仅约50页长。在Go中,类型标识仅意味着在所有方面都相同。没有理由使它变得更加复杂。 - peterSO

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接