关于Go中的接口类型是什么类型的官方说法?

pas*_*636 1 go

这是一个Go语法问题,似乎是一个愚蠢的问题,但是我一直在检查Go语言规范,以找到一些正式的单词或定义来定义xxx类型是什么类型,例如,接口类型是什么类型?

例如,我看到这样的词:

接口类型的方法集是其接口。

要么

必须将嵌入字段指定为类型名称T或指向非接口类型名称* T 的指针,并且T本身可能不是指针类型

要么

考虑具有两种方法的结构类型 T ...

type T struct {
  a int
}
....
Run Code Online (Sandbox Code Playgroud)

类型文字像是struct {...}struct类型,Ain type A struct {...}Bin type B interface{...}呢?是A结构类型和B接口类型吗?

是的,从上面关于struct type的示例中T,我可以看出,给定类型是struct type或interface type的已定义类型(通过“ type”声明)也是struct或interface type。因此A是struct类型,B也是interface类型。但是,此规则的正式定义在哪里?

对于定义的类型,我只能找到与类型类别有关的以下内容:

类型定义使用与给定类型相同的基础类型和操作创建一个新的独特类型,并将标识符绑定到该类型。

因此,我的理解是,定义的类型是具有给定类型的新的,不同的类型,但是它们属于同一类型类别,例如接口类型或结构类型。仍然没有这样的定义。

icz*_*cza 6

TLDR;

类型T接口,如果它的基础类型是一个接口类型。

类型T结构,如果其基本类型为结构类型。


Spec: Struct types and Spec: Interface types specifies exactly what are the struct and interface types:

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

InterfaceType      = "interface" "{" { MethodSpec ";" } "}" .
MethodSpec         = MethodName Signature | InterfaceTypeName .
MethodName         = identifier .
InterfaceTypeName  = TypeName .
Run Code Online (Sandbox Code Playgroud)

So for example these are struct types:

struct { A int }
struct {}
struct { _ int }
Run Code Online (Sandbox Code Playgroud)

and these are interface types:

interface { String() string }
interface {}
Run Code Online (Sandbox Code Playgroud)

We may use a type declaration to create a new type, such as:

type Point struct { X, Y int }
Run Code Online (Sandbox Code Playgroud)

The above type definition creates a new, distinct type with the same underlying type and operations as the given type, and binds an identifier to it. The definition of underlying type is recursive:

Each type T has an underlying type: If T is one of the predeclared boolean, numeric, or string types, or a type literal, the corresponding underlying type is T itself. Otherwise, T's underlying type is the underlying type of the type to which T refers in its type declaration.

When we talk about arbitrary types being structs or interfaces, we're talking about their kind.

In the light of this, basically your question is equivalent to this:

"When is the kind of an arbitrary type interface or struct?"

The answer to this question is not in the spec, but this is how we could define it:

The kind of a type T is interface if its underlying type is an interface type.

Similarly:

The kind of a type T is struct if its underlying type is a struct type.

So for example:

type Point struct { X, Y int }

type PP Point
Run Code Online (Sandbox Code Playgroud)

Is the type struct { X, Y int } of kind struct? Yes, because since it's a type literal, its underlying type is itself, and it's by definition a struct type.

Is Point a struct? Since the underlying type of Point is the underlying type of the type to which it refers in its type declaration, which is a type literal (see above), it is of struct type (its kind is struct).

Is PP a struct? Since its underlying type is the underlying type of the type to which it refers in its type declaration (which is Point), whose underlying type is a struct type literal, yes, it is also a struct type.

This kind we're talking about is represented by the reflect.Kind type. There are reflect.Interface and reflect.Struct constants (of type reflect.Kind) to represent the struct and interface kinds. And the reflect.Type type descriptor has a Type.Kind() method to access this kind.

This is how you can check if the type (kind) of some value is a struct for example:

func isStruct(i interface{}) bool {
    return reflect.TypeOf(i).Kind() == reflect.Struct
}
Run Code Online (Sandbox Code Playgroud)

Testing it (try it on the Go Playground):

fmt.Println(isStruct(Point{}))    // true
fmt.Println(isStruct(PP{}))       // true
fmt.Println(isStruct(struct{}{})) // true
fmt.Println(isStruct("text"))     // false
Run Code Online (Sandbox Code Playgroud)

Checking for interface type is a little more complicated because passing an interface value to a function that expects interface{} will not pass the interface value as-is but the concrete value "stored" in it, and as an interface{} value. We would have to pass a pointer to interface (which otherwise rarely makes sense in Go), access the element type and check its kind. For details, see this answer: What is the difference between reflect.ValueOf() and Value.Elem() in go?