Go 中针对未知接口的类型断言
通过反射检索对象的值并执行类型断言以获取实际对象的过程像这样的方法:
obj := new(User) out := reflect.ValueOf(obj).Elem().Interface().(User) fmt.Println(out == *obj) // true
是众所周知的。然而,当事先不知道对象的类型时,就会出现挑战。考虑一个接受未知接口的函数:
func Foo(obj interface{}) bool { // out := reflect.ValueOf(obj).Elem().Interface().( ... ) return out == *obj } func main() { obj := new(User) fmt.Println(Foo(obj)) }
在 Foo 函数中,无法确定传入对象的类型。这就提出了一个问题:在这种情况下如何执行类型断言?
答案在于类型断言的本质。即使在使用无法静态验证类型的接口时,类型断言也允许在 Go 中利用静态类型检查。此功能按照以下原则运行:
给定类型 t 的静态类型变量 s,编译器确保 s 始终保持类型 t。如果 s 被用作不同的类型,它会拒绝编译,因为这会违反既定的保证。
现在,想象一个接口变量 i。由于在编译时无法知道其类型,因此编译器无法保证将 i 分配给 s 不会破坏 s 的类型为 t 的保证。类型断言通过指出“我们将在运行时验证类型是否匹配,并仅在匹配时才执行分配”来解决此问题。编译器批准这种方法,因为它相信只有当类型兼容时才会发生赋值,从而保留 s 为 t 类型的保证。
本质上,这意味着在运行时发生以下情况:
if (i has type t) { s = i } else { s = t{} // Zero value of t }
所请求的功能是不可能的,因为编译器需要知道要执行检查的类型。如果没有这些知识,就无法确定 s 的静态类型,从而导致验证过程不可行。
以上是Go 中如何对未知接口执行类型断言?的详细内容。更多信息请关注PHP中文网其他相关文章!