go generate命令怎么使用
导读:本文共3400.5字符,通常情况下阅读需要11分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: “go generate”命令的作用是在编译前自动化生成某类代码;它常用于自动生成代码,它可以在代码编译之前根据源代码生成代码。当运行“go generate”命令时,它将扫描与当前包相关的源代码文件,找出所有包含“//go:generate”的特殊... ...
目录
(为您整理了一些要点),点击可以直达。
“go generate”命令的作用是在编译前自动化生成某类代码;它常用于自动生成代码,它可以在代码编译之前根据源代码生成代码。当运行“go generate”命令时,它将扫描与当前包相关的源代码文件,找出所有包含“//go:generate”的特殊注释,提取并执行该特殊注释后面的命令。
Go语言提供了一系列强大的工具,灵活使用这些工具,能够让我们的项目开发更加容易,工具集包含如下。
bugstartabugreportbuildcompilepackagesanddependenciescleanremoveobjectfilesandcachedfilesdocshowdocumentationforpackageorsymbolenvprintGoenvironmentinformationfixupdatepackagestousenewAPIsfmtgofmt(reformat)packagesourcesgenerategenerateGofilesbyprocessingsourcegetadddependenciestocurrentmoduleandinstalltheminstallcompileandinstallpackagesanddependencieslistlistpackagesormodulesmodmodulemaintenanceruncompileandrunGoprogramtesttestpackagestoolrunspecifiedgotoolversionprintGoversionvetreportlikelymistakesinpackages
工具的源码位于$GOPATH/src/cmd/internal,本篇文章主要讨论Go工具generate。
go语言自动化工具
go generate命令是在Go语言 1.4 版本里面新添加的一个命令,常用于自动生成代码,它可以在代码编译之前根据源代码生成代码。当运行go generate时,它将扫描与当前包相关的源代码文件,找出所有包含"// go:generate"的注释语句,提取并执行该注释后的命令,命令为可执行程序。该过程类似于调用执行shell脚本。
使用方法
添加特殊注释
//go:generatecommandargument...
执行generate命令
$gogenerate[-runregexp][-n][-v][-x][buildflags][file.go...|packages]
注意事项
该特殊注释必须包含在.go源码文件中。
每个源码文件可以包含多个generate特殊注释。
go generate不会被类似go build,go get,go test等命令触发执行,必须由开发者显式使用。
命令执行是串行的,如果出错,后续命令不再执行。
特殊注释必须以“//go:generate”开头,双斜线之后没有空格。
执行命令必须是系统PATH(echo $PATH)下的可执行程序。
使用示例
packagemainimport"fmt"//go:generateechoGoGoGo!//go:generategorunmain.go//go:generateecho$GOARCH$GOOS$GOFILE$GOLINE$GOPACKAGEfuncmain(){fmt.Println("gorummain.go!")}
执行go generate命令
$gogenerateGoGoGo!gorummain.go!amd64darwinmain.go7main
为枚举常量实现String方法
看完上述generate的简单介绍,可能读者并没有感受到该工具的强大之处,小菜刀提供一个该工具的经典应用场景:为枚举常量实现String方法。
这里需要提及官方的另外一个工具stringer,它可以自动为整数常量集编写String()方法。由于stringer并不在Go官方发行版的工具集里,我们需要自行安装,执行如下命令。
gogetgolang.org/x/tools/cmd/stringer
这里引用stringer文档中的一个示例。代码如下,其定义了一组不同Pill类型的整数常量。
packagepainkillertypePillintconst(PlaceboPill=iotaAspirinIbuprofenParacetamolAcetaminophen=Paracetamol)
为了进行调试或者其他原因,我们希望这些常量能够打印出来,这意味着Pill要有一个带有签名的方法。
func(pPill)String()string
要实现它,非常简单。
func(pPill)String()string{switchp{casePlacebo:return"Placebo"caseAspirin:return"Aspirin"caseIbuprofen:return"Ibuprofen"caseParacetamol://==Acetaminophenreturn"Paracetamol"}returnfmt.Sprintf("Pill(%d)",p)}
试想,如果我们的Pill名单里新增了一批药品名,每次增加或修改药品名,在相应的签名函数里,也都需要进行更改。这样岂不是很麻烦且很可能遗漏或出错?这时,我们可以通过 go generate + stringer的方案解决该问题。很简单,只需在定义Pill的代码中,增加一句注释语句即可。
//go:generatestringer-type=Pill
上面的命令,代表运行stringer工具来为Pill类型生成String方法,默认输出到pill_string.go文件中,执行如下。
$gogenerate$catpill_string.go//Codegeneratedbystringer-typePillpill.go;DONOTEDIT.packagepainkillerimport"fmt"const_Pill_name="PlaceboAspirinIbuprofenParacetamol"var_Pill_index=[...]uint8{0,7,14,23,34}func(iPill)String()string{ifi<0||i+1>=Pill(len(_Pill_index)){returnfmt.Sprintf("Pill(%d)",i)}return_Pill_name[_Pill_index[i]:_Pill_index[i+1]]}
这样,每次我们对Pill类型有修改时,我们所需要做的就是运行以下语句即可。
$gogenerate
当然,你要是觉得这样麻烦,或者担心忘记执行generate语句。那么,可以将go generate语句写入Makefile之中,置于go build命令之前,实现代码生成与编译的自动化。
值得一提的是,在Go源码文档中,大量采用了go generate+stringer的方案实现对枚举常量的String方法。在小菜刀本机Go 1.14.1的源码下,一共有23处使用,具体如下。
</div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
go generate命令怎么使用的详细内容,希望对您有所帮助,信息来源于网络。