Code

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
package main

import (
"bufio"
"encoding/gob"
"io"
)

type GobCodec struct {
conn io.ReadWriteCloser
buf *bufio.Writer
dec *gob.Decoder
enc *gob.Encoder
}

type Header struct {
}

type Codec interface {
io.Closer
ReadHeader(*Header) error
ReadBody(interface{}) error
Write(*Header, interface{}) error
}

func main() {
var ok Codec = (*GobCodec)(nil) // 这段代码编译是不通过的,因为 `GobCodec` 没有实现 `Codec` 接口的所有方法
}

如果将代码修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
"fmt"
"io"
)

type GobCodec struct {
io.Closer
}

type Header struct {
}

type Codec interface {
io.Closer
}

func main() {
var v Codec = (*GobCodec)(nil)

fmt.Println(v) // 输出 nil,v变量保存的是 `GobCodec` 的值
}

解释

var _:在 Go 中,下划线 _ 是一个匿名占位符,表示不关心这个变量的值。它通常用于在编译时避免未使用的变量或导入包而不使用包中的内容等情况。

Codec:这是一个接口类型,我们要检查是否被 *GobCodec 类型实现。

(*GobCodec)(nil):这是将 nil 转换为 *GobCodec 类型的方式,也就是创建一个 *GobCodec 类型的空指针。

整体来说,这行代码的目的是在编译时检查 *GobCodec 类型是否实现了 Codec 接口。尽管这个检查在编译时进行,但它确保了在运行时,任何 *GobCodec 类型的值都可以赋值给 Codec 接口变量,因为编译器已经确认它们满足了接口的要求。

这种技巧通常用于确保类型实现了接口,而不需要在实际代码中创建该类型的实例。这对于编写通用库或框架时非常有用,可以在不引入额外实例的情况下,对接口的实现进行静态验证。