dtvnbe1428 2019-08-22 16:25
浏览 83
已采纳

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

This is a Go grammar question and seems a stupid question but I've been checking the Go language specification to find some official words or definitions to define what type is a xxx type, say, what type is an interface type?

For example, I see words like these:

The method set of an interface type is its interface.

Or

An embedded field 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.

Or

Consider a struct type T with two methods ...

type T struct {
  a int
}
....

A type literal like struct {...} is a struct type, what about A in type A struct {...} and B in type B interface{...}? Is A a struct type and B an interface type?

Yes, from the above sample for the struct type T, I can tell that a defined type (by the "type" declaration) whose given type is a struct type or interface type is also a struct or interface type. So A is a struct type and B is an interface type also. But where are the official definitions of this rule?

For defined types I can only find the following relating to type categories:

A type definition creates a new, distinct type with the same underlying type and operations as the given type, and binds an identifier to it.

So my understanding is that the defined type is a new, distinct type with the given type, but they are in the same type category, say, interface types or struct types. Still, there are no such definitions.

  • 写回答

2条回答 默认 最新

  • douduan9129 2019-08-22 17:02
    关注

    TLDR;

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

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


    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 .
    

    So for example these are struct types:

    struct { A int }
    struct {}
    struct { _ int }
    

    and these are interface types:

    interface { String() string }
    interface {}
    

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

    type Point struct { X, Y int }
    

    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
    

    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
    }
    

    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
    

    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?

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 C#调用python代码(python带有库)
  • ¥15 矩阵加法的规则是两个矩阵中对应位置的数的绝对值进行加和
  • ¥15 活动选择题。最多可以参加几个项目?
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题
  • ¥20 云服务Linux系统TCP-MSS值修改?
  • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)
  • ¥20 怎么在stm32门禁成品上增加查询记录功能
  • ¥15 Source insight编写代码后使用CCS5.2版本import之后,代码跳到注释行里面
  • ¥50 NT4.0系统 STOP:0X0000007B