Golang如何为未知接口做类型断言?

Mar*_*oni 9 go

我知道我可以通过反射得到一个对象的值,然后使用类型断言来获取实际对象:

obj := new(User)
out := reflect.ValueOf(obj).Elem().Interface().(User)
fmt.Println(out == *obj) // true
Run Code Online (Sandbox Code Playgroud)

但是,如果我不知道对象的类型是什么User,我该怎么做类型断言呢?说它在一个函数内部:

func Foo(obj interface{}) bool {
    // out := reflect.ValueOf(obj).Elem().Interface().( ... )
    return out == *obj
}

func main() {
    obj := new(User)
    fmt.Println(Foo(obj))
}
Run Code Online (Sandbox Code Playgroud)

Foo函数内部,您永远不会知道实际传递的对象类型,那么如何完成类型断言?

jos*_*hlf 11

你不能.类型断言允许您利用语言为您提供的静态类型检查,即使您有一个非静态检查类型的接口.它基本上是这样的:

你有一些静态类型的变量s,它有类型t.如果您尝试使用,就好像它是一个不同的类型,编译器通过拒绝编译来强制执行s始终具有类型的保证,因为这会破坏保证.ts

你也有一些接口变量,i.i的类型在编译时已知的,所以没有办法编译器可以保证分配is不会打破保证s有型t.但是,您可以做的是类型断言.类型断言一边说这个问题,说:"好吧,我会在运行时检查,如果类型匹配,我只会进行分配." 编译器对此没问题,因为它知道只有在类型匹配时才会发生赋值,这意味着它仍然可以保证s具有类型t.所以基本上在运行时发生的事情是:

if (i has type t) {
    s = i
} else {
    s = t{} // Zero value of t
}
Run Code Online (Sandbox Code Playgroud)

你要求的是不可能的原因是编译器必须知道你正在检查什么类型,以便它可以编写我上面给出伪代码的检查.不知道是什么t,没有办法知道静态类型s应该是什么,也无法检查它是否正确.

  • 您可以做的最好的事情是获得这种类型的接口值.像这样:`reflect.New(reflect.TypeOf(obj)).Interface()`. (2认同)