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

指向 Go 中的接口的指针

指向 Go 中的接口的指针

Go
小唯快跑啊 2021-07-06 12:53:01
我目前正在阅读https://github.com/codegangsta/inject go 包的源代码,以了解该包的工作原理。我有一些关于文件https://github.com/codegangsta/inject/blob/master/inject.go文件的问题,该文件使用了 Go 语言的一些元素,我不理解,也没有在文档中找到准确的解释.// InterfaceOf dereferences a pointer to an Interface type.// It panics if value is not an pointer to an interface.func InterfaceOf(value interface{}) reflect.Type {        t := reflect.TypeOf(value)        for t.Kind() == reflect.Ptr {                t = t.Elem()        }        if t.Kind() != reflect.Interface {                panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil)")        }        return t}我的第一个问题是关于for循环的。为什么它使用带有测试表达式的 for 循环?第二个与恐慌函数中的消息有关。“指向接口的指针”在(*MyInterface)(nil). 当您检查类型是否实现了结构时,我只在有关“编译时检查结构”的 go 文档中遇到类似的构造:var _ SomeType = (*SomeInterface)(nil)我没有找到有关带有(*Interface)(nil)接口和指针的语句的任何信息。我们应该如何解释这个说法?与指向接口的指针有什么关系,我在哪里可以找到有关指向接口的指针的信息?
查看完整描述

3 回答

?
哈士奇WWW

TA贡献1799条经验 获得超6个赞

总结两个 答案:


该for环

for t.Kind() == reflect.Ptr {

    t = t.Elem()

}

t.Elem()是反射等价于*t,所以t只要它持有另一个指针值,这个循环就会解除引用。在循环结束时,t将保存最后一个指针指向的值,不再是指针。


消息

使用不是指向接口的指针的值调用 [...]。 (*MyInterface)(nil)


该表达式(*MyInterface)(nil)只是预期参数的一个(措辞不佳)示例。


语法是转换的语法。在这种情况下,转换将尝试将值(在本例中nil)转换为给定类型 ( *MyInterface)。所以,


(*MyInterface)(nil) 

会给你一个*MyInterface接口类型为MyInterface( play )的零值:


x := (*MyInterface)(nil)

InterfaceOf(x) // MyInterface

当然,这个值并没有指向有意义的地方。


接口实现的编译时检查

为避免混淆,您展示的构造


var _ SomeType = (*SomeInterface)(nil)


可能不是您想要的。我猜你想要这个:


var _ SomeInterface = (*SomeType)(nil)

此构造启用对某些类型的接口实现的编译时检查。因此,如果您正在编写某种类型的库,并且希望在不使用它的情况下满足接口,则可以使用它来确保您的结构实现了该接口。


为什么这有效


首先,var _ someType是一个将由编译器检查的变量,但不会出现在已编译的程序中,并且由于空白标识符_而无法访问:


空白标识符可以像声明中的任何其他标识符一样使用,但它不引入绑定,因此没有声明。


这使您可以在不干扰程序的其余部分的情况下声明任意数量的这些构造。


您可以通过编写以下代码声明任何类型的指针的零值:


(*T)(nil)

在 play 上检查这个例子。


接下来,可分配性表示x可分配给TifT是一个接口并x实现T。


所以总结一下:


T _ = (*x)(nil)

强制执行x工具T的一切将是一个错误。


查看完整回答
反对 回复 2021-07-19
?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

for循环与while其他语言中的循环相同

第二件事只是转换的语法:

(*Point)(p)      // p is converted to *Point

因为这个库是如何工作的,你只需要将指针传递给接口,for 循环然后取消引用它(如果我们传递类似 (***MyInterface)(nil)),然后 if 语句检查 ty[e 指向的是否是一个界面。


查看完整回答
反对 回复 2021-07-19
  • 3 回答
  • 0 关注
  • 289 浏览
慕课专栏
更多

添加回答

举报

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