go 接口静态与动态校验
go 的接口是duck模型,类型不需要显式的声明实现某个接口,只需实现该接口的所有methods,就认为该类型实现该接口。在实际中,大部分接口转换是静态的,发生在编译时刻;go 也支持动态接口转换,转换发生在运行时。
比如,需要传递 *os.File
到一个需要io.Reader参数的函数,如果*os.File
没有实现接口io.Reader,则程序在编译期就无法通过;
有些接口装换发生在运行期,一个实例就是 encoding/json 包,其定义了一个
Marshaler
接口,当JSON解析器接收的value实现该接口,就调用该value的marshaling
方法转换,反之则调用系统默认的转换器。这种转换可以通过go的type类型断言实现:
if m, ok := val.(json.Marshaler); ok { xxx } else { xxx }
if str, ok := value.(string); ok { return str } else if str, ok := value.(Stringer); ok { return str.String() }
有时我们为了提高程序健壮性或者为了防止接口发生变更而具体实现类型忘记变更导致程序运行时崩溃,我们需要将运行期的校验提前到编译期进行,这时可以采用如下方式:
var _ json.Marshaler = (*RawMessage)(nil)此语句将在编译期将*RawMessage 转换为json.Marshaler,如果接口Marshaler发生变化,而RawMessage 没有变化,编译将不能通过,从而使我们提前发现问题,进行修改,而不会因为一时疏忽将该问题推迟到运行时才发现。这里的_仅仅用来进行类型校验,而不是真的去创建一个变量。但是不要滥用该方法,该方法仅仅使用在没有静态转换,但是有要保证程序安全的额地方。
有疑问加站长微信联系(非本文作者)