我目前正在阅读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
}
Run Code Online (Sandbox Code Playgroud)
我的第一个问题是关于for循环的。为什么它使用带有测试表达式的 for 循环?
第二个与恐慌函数中的消息有关。中提到了“指向接口的指针” (*MyInterface)(nil)。当您检查类型是否实现结构时,我只会在有关“编译时检查结构”的 go 文档中遇到类似的构造:
var _ SomeType = (*SomeInterface)(nil)
Run Code Online (Sandbox Code Playgroud)
我没有找到任何有关带有(*Interface)(nil)接口的声明和指针的信息。
我们该如何解读这个说法呢?与接口指针有什么关系?在哪里可以找到有关接口指针的信息?
forfor t.Kind() == reflect.Ptr {
t = t.Elem()
}
Run Code Online (Sandbox Code Playgroud)
t.Elem()是相当于 的反射*t,那么t只要它保存另一个指针值,这个循环就会取消引用。在循环结束时,t将保存最后一个指针指向的值,不再是指针。
使用不是指向接口的指针的值调用 [...]。
(*MyInterface)(nil)
该表达式(*MyInterface)(nil)只是预期参数的一个(措辞不佳的)示例。
语法是转换的语法。在本例中,转换将尝试将值(在本例中nil为 )转换为给定类型 ( *MyInterface)。所以,
(*MyInterface)(nil)
Run Code Online (Sandbox Code Playgroud)
将为您提供一个零值,*MyInterface其接口类型为MyInterface( play ):
x := (*MyInterface)(nil)
InterfaceOf(x) // MyInterface
Run Code Online (Sandbox Code Playgroud)
当然,这个值并没有指向有意义的地方。
为了避免混淆,您展示的结构
var _ SomeType = (*SomeInterface)(nil)
可能不是你想要的。我猜你想要这个:
var _ SomeInterface = (*SomeType)(nil)
Run Code Online (Sandbox Code Playgroud)
此构造允许对某些类型的接口实现进行编译时检查。因此,如果您正在编写某种类型的库,并且想要满足接口而不使用它,则可以使用它来确保您的结构实现该接口。
为什么这有效
首先,var _ someType是一个将由编译器检查的变量,但不会出现在已编译的程序中,并且由于空白标识符_而无法访问:
空白标识符可以像声明中的任何其他标识符一样使用,但它不会引入绑定,因此不会被声明。
这使您能够声明任意数量的这些构造,而不会干扰程序的其余部分。
您可以通过编写以下内容来声明任何类型的指针的零值:
(*T)(nil)
Run Code Online (Sandbox Code Playgroud)
请在播放时查看此示例。
接下来,可分配性表示如果是一个接口并且实现 则可x分配给。TTxT
总结一下:
T _ = (*x)(nil)
Run Code Online (Sandbox Code Playgroud)
强制x执行T,因为其他一切都会出错。
| 归档时间: |
|
| 查看次数: |
1527 次 |
| 最近记录: |