为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
素胚勾勒不出你 2023-07-17 14:16:44
这是一个 Go 语法问题,看起来是一个愚蠢的问题,但我一直在检查Go 语言规范,找到一些官方单词或定义来定义什么类型是 xxx 类型,比如说,什么类型是接口类型?例如,我看到这样的词:接口类型的方法集就是它的接口。或者嵌入字段必须指定为类型名称 T 或指向非接口类型名称 *T 的指针,并且 T 本身可能不是指针类型。或者考虑一个具有两种方法的结构类型T ...type T struct {  a int}....像结构类型这样的类型文字struct {...},那么Ain type A struct {...}和Bin呢type B interface{...}?是A结构体类型还是B接口类型?是的,从上面的结构类型示例中T,我可以看出,其给定类型是结构类型或接口类型的已定义类型(通过“类型”声明)也是结构或接口类型。A结构类型也是如此,B接口类型也是如此。但这条规则的官方定义在哪里?对于定义的类型,我只能找到以下与类型类别相关的内容:类型定义创建一个新的、不同的类型,其具有与给定类型相同的基础类型和操作,并将标识符绑定到它。所以我的理解是,定义的类型是与给定类型不同的新类型,但它们属于同一类型类别,例如接口类型或结构类型。尽管如此,仍然没有这样的定义。
查看完整描述

2 回答

?
慕少森

TA贡献2019条经验 获得超9个赞

太长了;

如果其基础类型T接口类型,则类型的种类是接口。

如果其基础类型是结构体类型,则该类型是结构体。T


规范:结构类型和规范:接口类型准确指定了结构和接口类型:

StructType    = "struct" "{" { FieldDecl ";" } "}" .

FieldDecl     = (IdentifierList Type | EmbeddedField) [ Tag ] .

EmbeddedField = [ "*" ] TypeName .

Tag           = string_lit .


InterfaceType      = "interface" "{" { MethodSpec ";" } "}" .

MethodSpec         = MethodName Signature | InterfaceTypeName .

MethodName         = identifier .

InterfaceTypeName  = TypeName .

例如,这些是结构类型:


struct { A int }

struct {}

struct { _ int }

这些是接口类型:


interface { String() string }

interface {}

我们可以使用类型声明来创建新类型,例如:

type Point struct { X, Y int }

上面的类型定义创建了一个新的、不同的类型,其具有与给定类型相同的基础类型和操作,并将标识符绑定到它。底层类型的定义是递归的:

每个类型T都有一个基础类型:如果T是预声明的布尔、数字或字符串类型之一,或者类型文字,则相应的基础类型是T其本身。否则,的基础类型是其类型声明T中引用的类型的基础类型。T

当我们谈论任意类型(结构体或接口)时,我们谈论的是它们的类型

鉴于此,基本上你的问题相当于:

“什么时候是任意类型的接口或结构体?”

这个问题的答案不在规范中,但我们可以这样定义它:

如果类型的基础类型T接口类型,则该类型的种类是接口。

相似地:

如果类型的基础类型T结构体类型,则该类型的类型是结构体。

例如:

type Point struct { X, Y int }
type PP Point

struct { X, Y int }是kind struct的类型吗?是的,因为由于它是类型文字,所以它的基础类型就是它本身,并且根据定义它是结构类型。

Point一个结构体吗?由于 的基础类型Point是它在其类型声明中引用的类型的基础类型,即类型文字(见上文),因此它是 struct 类型(其种类是struct)。

PP一个结构体吗?由于它的基础类型是它在类型声明中引用的类型的基础类型(即Point),其基础类型是结构体类型文字,是的,它也是结构体类型。

我们所说的这种就是reflect.Kind用类型来表示的。有reflect.Interfacereflect.Struct常量(类型为reflect.Kind)来表示结构接口类型。并且reflect.Type类型描述符有一个Type.Kind()方法来访问这种类型。

这是检查某个值的类型(种类)是否为结构的方法,例如:

func isStruct(i interface{}) bool {

    return reflect.TypeOf(i).Kind() == reflect.Struct

}

测试它(在Go Playground上尝试一下):


fmt.Println(isStruct(Point{}))    // true

fmt.Println(isStruct(PP{}))       // true

fmt.Println(isStruct(struct{}{})) // true

fmt.Println(isStruct("text"))     // false

检查接口类型有点复杂,因为将接口值传递给期望的函数interface{}不会按原样传递接口值,而是“存储”在其中的具体值,并作为值传递interface{}。我们必须传递一个指向接口的指针(否则这在 Go 中很少有意义),访问元素类型并检查其类型。

查看完整回答
反对 回复 2023-07-17
?
弑天下

TA贡献1818条经验 获得超7个赞

接口类型是由关键字引入的类型interface,或者是由定义的类型的名称(当然还要加上该接口的实际要求)。type name interface

任何类型,无论是否是接口类型,如果具有适当的命名方法集,都可以实现接口类型。也就是说,struct类型可能足以与某些接口类型一起使用。即使是非struct类型也可能就足够了:

type foo int
func (receiver_arg foo) method1() { ... }

类型名称foo现在实现任何需要指定方法的接口method1(当然前提是它实现了其余的任何所需方法)。

...定义的类型[通过type关键字]是具有给定类型的新的、不同的类型,但它们属于同一类型类别...

是的,就是这样。使用reflect,你会发现它们有相同的Kindkind这个词并不像这样出现在规范中,但它非常有用,这里的链接枚举了 Go 中的所有基本类型。


查看完整回答
反对 回复 2023-07-17
  • 2 回答
  • 0 关注
  • 75 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信