go编译期接口断言 / 编译期接口检查(compile-time interface assertion / compile-time interface check)
https://go.dev/doc/effective_go#blank_implements
在编译期断言某类型实现了某接口
var _ I = (*T)(nil)
var _ 声明一个匿名变量(_ 表示丢弃,不会实际使用)
声明一个接口类型 I 的变量,把 *T 的零值赋给它。
- 编译期检查,零运行时开销:如果
*T没有实现接口I的所有方法,编译器直接报错,程序根本跑不起来。而_变量不会被使用,所以不会生成任何运行时代码。 - 提前暴露问题:不用等到运行时才发现类型没实现接口,在编译阶段就能捕获错误。
- 文档作用:其他开发者看到这一行,立刻就知道"类型 T 的指针是要实现接口 I 的",起到自文档化的效果。
- 不污染命名空间:用
_作为变量名,不会占用任何有意义的标识符。
var _ json.Marshaler = (*RawMessage)(nil)
目的是让编译器检查RawMessage有没完全实现json.Marshaler这个接口, 没有这句, 如果以后json.Marshaler加了新方法, 但RawMessage 没新加这个方法的实现, 编译时不会报错, 等用到时再报错就麻烦了.
或用把变量转成了接口, 然后调用接口中的方法, 但没实现, 现在提前检查就没这种问题.
这是一种零成本、编译期生效的"契约声明",是 Go 社区广泛采用的惯用写法(idiomatic Go),在 Effective Go 和标准库代码中都能看到。
浙公网安备 33010602011771号