go判断实现接口的方法 var _ Interface = (*Type)(nil)

阅读源码过程中发现很多var _ Interface = (*Type)(nil)写法,对于接口实现情况的判断十分优雅,而自己编写代码过程中鲜有涉及。

其作用就是用来检测*Type是否实现了Interface接口,有多种形式,具体见代码
这种定义方式主要用于在源码编译的时候检测预期的接口是否被实现,未实现将导致编译失败,并可提示缺少了哪些方法的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package main

import (
"fmt"
"reflect"
)

type I interface {
Foo()
}

type T struct{}
type F struct{}

func (t T) Foo() {} // 注释掉编译将报错 cannot use (*T)(nil) (type *T) as type I in assignment: *T does not implement I (missing Foo method)

// 判断*T是否实现了IA接口,未实现编译时将报错
var _ I = (*T)(nil) // 将nil转为*T类型后判断是否实现I接口
var _ I = &T{}
var _ I = new(T)

// 判断T是否实现了IA接口,未实现编译时将报错
var _ I = T{}

func main() {
// _ = []int([]int64{}) // cannot convert []int64{} (type []int64) to type []int

// 可被定义为nil的类型,将nil转换为这些类型
n1 := (*struct{})(nil) // 指针
fmt.Printf("(*struct{})(nil) nil: %t ,type is: %s\n", n1 == nil, reflect.TypeOf(n1).String())

n2 := []int(nil) // 切片
fmt.Printf("[]int(nil) nil: %t ,type is: %s\n", n2 == nil, reflect.TypeOf(n2).String())

n3 := map[int]bool(nil) // map
fmt.Printf("map[int]bool(nil) nil: %t ,type is: %s\n", n3 == nil, reflect.TypeOf(n3).String())

n4 := chan string(nil) // channel
fmt.Printf("chan string(nil) nil: %t ,type is: %s\n", n4 == nil, reflect.TypeOf(n4).String())

n5 := (func())(nil) // 函数
fmt.Printf("(func())(nil) nil: %t ,type is: %s\n", n5 == nil, reflect.TypeOf(n5).String())

n6 := interface{}(nil) // 接口,可任意赋值
fmt.Printf("interface{}(nil) nil: %t \n", n6 == nil)

// 下面这些行跟上面的等价
var _ *struct{} = nil
var _ []int = nil
var _ map[int]bool = nil
var _ chan string = nil
var _ func() = nil
var _ interface{} = nil

// 报错 use of untyped nil
// var _ = nil
}

参考链接

uber-go
原文链接