忽略返回值
這個應該是最簡單的用途譬挚,比如某個函數(shù)返回三個參數(shù),但是我們只需要其中的兩個,另外一個參數(shù)可以忽略掰吕,這樣的話代碼可以這樣寫:
v1, v2, _ := function(...)
v1, _, _ := function(...)
如果沒有產(chǎn)生新變量
_, _, _ = function(...)
_ = json.Unmarshal(...)
用在函數(shù)定義中省略帶名的參數(shù)
func demo() ( int, int, string, int ,error)
返回多個參數(shù)時,尤其是類型相同的版保,不利于閱讀呜笑,
func demo() ( sumA int, sumB int, _ string, total int ,_ error)
返回參數(shù) int 加了名字,對比上面,便于理解,但是 "string" 和 "error"沒有名字彻犁,編譯會報錯叫胁,用下劃線可以忽略命名
用在變量(特別是接口斷言)
例如我們定義了一個接口(interface):
type Animal interface {
Say()
}
然后定義了一個結(jié)構(gòu)體(struct)
type Dog struct {
}
然后我們希望在代碼中判斷Dog這個struct是否實現(xiàn)了Animal這個interface
var _ Animal = Dog{}
上面用來判斷Dog是否實現(xiàn)了Animal, 用作類型斷言,如果Dog沒有實現(xiàn)Animal汞幢,則會報編譯錯誤
用在import package
假設我們在代碼的import中這樣引入package:
import _ "test/foo"
這表示在執(zhí)行本段代碼之前會先調(diào)用test/foo中的初始化函數(shù)(init)驼鹅,這種使用方式僅讓導入的包做初始化,而不使用包中其他功能
例如我們定義了一個Foo struct森篷,然后對它進行初始化
package foo
import "fmt"
type Foo struct {
Id int
Name string
}
func init() {
f := &Foo{Id: 123, Name: "abc"}
fmt.Printf("init foo object: %v\n", f)
}
然后在main函數(shù)里面引入test/foo
package main
import (
"fmt"
_ "test/foo"
)
func main() {
fmt.Printf("hello world\n")
}
運行結(jié)果如下
init foo object: &{123 abc}
hello world
我們可以看到:在main函數(shù)輸出”hello world”之前就已經(jīng)對foo對象進行初始化了输钩!
版本校驗,編譯時斷言
在使用gRPC的時候仲智,看到通過 const 來做版本校驗买乃,因為他牽涉到多個項目多個包,生成的 pb.go 文件需要指定具體版本信息
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
常量 proto.ProtoPackageIsVersion4
在業(yè)務代碼中不會被調(diào)用到钓辆,因此無法通過明確調(diào)用的方式來迫使編譯器報錯剪验,因此可以再定義個常量來引用它
const _ = proto.ProtoPackageIsVersion4
或者
const vs4 = proto.ProtoPackageIsVersion4
比如,有些版本并未發(fā)生大的改動前联,無論是編譯還是運行都不會有影響功戚,但是運行結(jié)果不同,因此需要顯示的做版本限制蛀恩。