一些实用的Go工具命令

命令 作用
gofmt -w -l -r "panic(err) -> log.Error(err)" . 格式化并替换文本
go test -v 将 t.Log 的输出变成实时流式,而不是在整个测试结束之后输出
go mod why -m 分析特定的模块为什么会在 go.mod 文件中

Go语言自带工具集

bug         start a bug report
build       compile packages and dependencies
clean       remove object files and cached files
doc         show documentation for package or symbol
env         print Go environment information
fix         update packages to use new APIs
fmt         gofmt (reformat) package sources
generate    generate Go files by processing source
get         add dependencies to current module and install them
install     compile and install packages and dependencies
list        list packages or modules
mod         module maintenance
run         compile and run Go program
test        test packages
tool        run specified go tool
version     print Go version
vet         report likely mistakes in packages

go generate

  1. go generate常用于自动生成代码,它可以在代码编译之前根据源代码生成代码。
  2. 当运行go generate时,它将扫描与当前包相关的源代码文件,找出所有包含"// go:generate"的注释语句,提取并执行该注释后的命令,命令为可执行程序。
  3. 该过程类似于调用执行shell脚本。

添加特殊注释

//go:generate command argument...

执行generate命令

go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]

注意事项

  1. 该特殊注释必须包含在.go源码文件中。
  2. 每个源码文件可以包含多个generate特殊注释。
  3. go generate不会被类似go build,go get,go test等命令触发执行,必须由开发者显式使用。
  4. 命令执行是串行的,如果出错,后续命令不再执行。
  5. 特殊注释必须以“//go:generate”开头,双斜线之后没有空格。
  6. 执行命令必须是系统PATH(echo $PATH)下的可执行程序。

go generate 示例

package main

import "fmt"

//go:generate echo HelloWorld!
//go:generate go run main.go
//go:generate echo $GOARCH $GOOS $GOFILE $GOLINE $GOPACKAGE

func main() {
 fmt.Println("go run main.go!")
}

常用场景

为枚举常量实现String方法

//go:generate stringer -type=XXXXX(枚举的别名)

首先安装Go官方工具stringer:

go install golang.org/x/tools/cmd/stringer

其它常用命令

go tool compile -S main.go 生成汇编代码
go build -gcflags -S main.go

禁止内联

//go:noinline
func smallAllocation() *smallStruct {
   return &smallStruct{}
}

逃逸分析命令

go tool compile -S main.go //输出汇编内容,从中也可以看出逃逸的信息。用 go tool compile -help 可以查看所有可以传递给编译器的标识参数
go build -gcflags '-N -l -m' main.go //禁止优化、禁止内联、打印逃逸分析信息

GODEBUG

GC垃圾回收分析命令

GODEBUG=gctrace=1 go run main.go

调度器观察参数

GODEBUG=schedtrace=100 go run main.go //在运行时每100毫秒发出一行调度器的摘要信息到标准err输出中
GODEBUG=scheddetail=1,schedtrace=100 go run main.go //在运行时每100毫秒发出一次详细的多行信息,信息内容包括调度程序、处理器、OS线程和goroutine的状态

说明如下:

**GODEBUG=schedtrace=100 go run main.go**
SCHED 0ms: gomaxprocs=16 idleprocs=14 threads=4 spinningthreads=1 idlethreads=0 runqueue=0 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# command-line-arguments
SCHED 0ms: gomaxprocs=16 idleprocs=14 threads=3 spinningthreads=1 idlethreads=0 runqueue=0 [2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
SCHED 104ms: gomaxprocs=16 idleprocs=15 threads=20 spinningthreads=1 idlethreads=13 runqueue=0 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# command-line-arguments
SCHED 0ms: gomaxprocs=16 idleprocs=14 threads=3 spinningthreads=1 idlethreads=0 runqueue=0 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
SCHED 207ms: gomaxprocs=16 idleprocs=16 threads=20 spinningthreads=0 idlethreads=13 runqueue=0 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
SCHED 316ms: gomaxprocs=16 idleprocs=16 threads=20 spinningthreads=0 idlethreads=13 runqueue=0 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
SCHED 0ms: gomaxprocs=16 idleprocs=13 threads=5 spinningthreads=1 idlethreads=0 runqueue=0 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
SCHED 416ms: gomaxprocs=16 idleprocs=15 threads=20 spinningthreads=1 idlethreads=13 runqueue=0 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
SCHED 100ms: gomaxprocs=16 idleprocs=16 threads=5 spinningthreads=0 idlethreads=3 runqueue=0 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
SCHED 526ms: gomaxprocs=16 idleprocs=16 threads=20 spinningthreads=0 idlethreads=13 runqueue=0 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]

解释:
sched:每一行都代表调度器的调试信息,后面的毫秒数是表示从启动到现在的时间,是由schedtrace值设置的。
gomaxprocs:当前的cpu核心数
idleprocs:空闲的处理器数量
threads:OS线程数量,后面的数字表示当前正在运行的线程数量
spinningthreads:自旋状态的OS线程数量。(调度器的设计者在考虑了“OS的资源利用率”和“频繁的线程抢占给OS带来的负载”之后,提出了自旋线程的概念。当自旋线程没有找到可供其调度执行的goroutine时,并不会销毁改线程,而是采取自旋的操作保存了下来。虽然看起来浪费了一些资源,但是考虑一下syscall的情景就可以知道,比起自旋操作,线程间频繁的抢占、创建和销毁操作带来的危害更大。)
idlethreads:空闲的线程数量
runqueue:全局队列中的goroutine数量,后面的[0 ...]表示这16个P的本地队列正在运行的goroutine数量。
**GODEBUG=scheddetail=1,schedtrace=100 go run main.go**
SCHED 0ms: gomaxprocs=16 idleprocs=14 threads=4 spinningthreads=1 idlethreads=0 runqueue=0 gcwaiting=0 nmidlelocked=0 stopwait=0 sysmonwait=0
  P0: status=1 schedtick=0 syscalltick=0 m=0 runqsize=0 gfreecnt=0 timerslen=0
  P1: status=1 schedtick=0 syscalltick=0 m=3 runqsize=0 gfreecnt=0 timerslen=0
  P2: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  P3: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  P4: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  P5: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  P6: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  P7: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  P8: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  P9: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  P10: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  P11: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  P12: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  P13: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  P14: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  P15: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0
  M3: p=1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=2 dying=0 spinning=false blocked=false lockedg=-1
  M2: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=2 dying=0 spinning=false blocked=false lockedg=-1
  M1: p=-1 curg=17 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 spinning=false blocked=false lockedg=17
  M0: p=0 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=1
  G1: status=1() m=-1 lockedm=0
  G17: status=6() m=1 lockedm=1
  G2: status=1() m=-1 lockedm=-1

解释:
G的运行状态共有 9 种,分别为:
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
(9)