我现在遇到的情况与在该线程中询问的情况相同: 具有嵌入式匿名接口的结构的含义?
type A interface { Foo() string } type B struct { A bar string }
习惯上,来自OOP语言的背景,这种模式对我来说似乎是“试图说”,因为B必须实现接口A。但是现在我知道“ Go是不同的”。因此,无论有没有进行编译,它都比我最初期望的编译时检查要好。
func (B) Foo() string { .... }
当下。正如上面的问题指出的那样(解释):“在仅希望实现接口的/ part /的情况下,在结构中使用嵌入式接口非常有用”。
据推测,这是因为此嵌入发生的情况与其他所有情况一样-类型B的值将具有类型A的匿名接口值作为字段。就我个人而言,虽然我发现正交性令人欣慰,但同时也使反射包让我以这种方式直接从B的类型中获取A的方法感到困惑,而如果没有使用接收方B的方法,则不会出错/为零。但是- 这个问题不是关于其背后的想法-它是关于在以下情况下如何初始化接口值b := B{}:
b := B{}
func main() { bType := reflect.TypeOf(B{}) bMeth, has := bType.MethodByName("Foo") if has { fmt.Printf("HAS IT: %s\n",bMeth.Type.Kind()) res := bMeth.Func.Call([]reflect.Value{reflect.ValueOf(B{})}) val := res[0].Interface() fmt.Println(val) } else { fmt.Println("DOESNT HAS IT") } }
运行此命令时,会导致严重的恐慌
HAS IT: func panic: runtime error: invalid memory address or nil pointer dereference
… 或没有 -取决于编译器/运行时是否能够找到上述方法。因此: 在触发该情况之前如何检测到该情况?
那就是- 关于bMeth值,我可以用来查看反射返回的Method和func值中没有“真实”实现吗?更确切地说,是像“指向匿名接口值的函数表中的函数的指针为零”,还是从没有实现的反射的接口中拉出的方法到底发生了什么?
将整个过程包装在goroutine中并尝试在defer / panic下运行该函数不是答案-不仅因为panic / defer的开销很大,而且因为该函数通常(如果 确实 存在)可能会产生副作用我现在不想要…
我是否需要类似编译器类型检查的运行时实现之类的东西?还是有更简单的方法?我在想这个吗?
上面的示例在Go游乐场
你不需要在我心中反思
method_in_table := B.Foo fmt.Printf("%T \n", method_in_table)
将输出你
func(main.B) string
接口类型A在预先声明的nil初始化,没有动态类型
var a A if a==nil{ fmt.Printf("It's nil") } a.Foo()
会给你同样的错误。所以实际检查可以
if b.A != nil { b.Foo()}