_

用在 import

在导包的时候,常见这个用法,尤其是项目中使用到 mysql 或者使用 pprof 做性能分析时,比如

import _ "net/http/pprof"
import _ "github.com/go-sql-driver/mysql"
init()

用在返回值

该用法也是一个常见用法。golang 中的函数返回值一般是多个,err 通常在返回值最后一个值。但是,有时候函数返回值中的某个值我们不关心,如何接收了这个值但不使用,代码编译会报错,因此需要将其忽略掉。比如

for _, val := range slice {}
_, err := func()

用在变量

我们都知道 go 语言的接口是非侵入式的,不像 java 和 c++ 那么重,一个结构体只要实现了接口定义的所有函数,我们就说这个接口实现了该接口。有个专门的名字表示这种行为,duck typing,即当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子

type i interface {
  sing()
}

type t struct { 
}

func (t t) sing() {
}

type t2 struct {  
}

func (t *t2) sing() {
}

// 编译通过
var _ i = t{}
// 编译通过
var _ i = &t{}

// 编译失败
var _ i = t2{}
// 编译通过
var _ i = &t2{}

在这里下划线用来判断结构体是否实现了接口,如果没有实现,在编译的时候就能暴露出问题,如果没有这个判断,后代码中使用结构体没有实现的接口方法,在编译器是不会报错的。

可以看到上面四个判断只有第三个编译时失败的,报错如下:

./test.go:27:5: cannot use t2 literal (type t2) as type i in assignment:
    t2 does not implement i (sing method has pointer receiver)

t  sing  *t2 sing 

我们都知道,go 语言中是按值传递的。

t2sing  t2  &t2 sing 
 t  *t sing 

当然,这些都是我的个人理解,如果不对的话,欢迎斧正。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。