Golang具有一套可以构建和处理go源代码的程序,作为命令行工具,这些程序也并非直接运行,而是由go程序调用。运行这些程序最常见的方式是作为go程序的子命令,例如 go fmt,该命令的运行方式是由go程序使用适合于包级处理的参数调用底层二进制文件,对go源代码的完整包进行操作;这些程序也可以作为独立的二进制文件运行,使用go tool子命令(如go tool cgo)使用未修改的参数;某些命令(如pprof)只能通过go tool子命令访问。go命令行作为日常开发的工具,能大大方便编译、调试、诊断程序性能等工作,本文是对常见go命令行工具使用的汇总
go命令
go命令管理go源代码并运行此处列出的其他命令。在终端输入go,会打印出如下信息
$ go
Go is a tool for managing Go source code.
Usage:
go <command> [arguments]
The commands are:
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
Use "go help <command>" for more information about a command.
Additional help topics:
buildmode build modes
c calling between Go and C
cache build and test caching
environment environment variables
filetype file types
go.mod the go.mod file
gopath GOPATH environment variable
gopath-get legacy GOPATH go get
goproxy module proxy protocol
importpath import path syntax
modules modules, module versions, and more
module-get module-aware go get
module-auth module authentication using go.sum
module-private module configuration for non-public modules
packages package lists and patterns
testflag testing flags
testfunc testing functions
Use "go help <topic>" for more information about that to![]()pic.
下面介绍命令部分
启动错误报告 运行go bug
命令,Bug打开默认浏览器并启动新的Bug报告,报告包括有用的系统信息
编译包和依赖项 用法如下
go build [-o output] [-i] [build flags] [packages]
build编译由导入路径命名的包及其依赖项,但不安装编译结果。如果build的参数是来自单个目录的.go文件列表,则build会将它们视为指定单个包的源文件列表;编译包时,build将忽略以"_test.go"结尾的文件
在编译单个main包时,build将生成的可执行文件写入以第一个源文件(go build ed.go rx.go
输出的二进制文件名为 'ed' 或 'ed.exe')或源代码目录(go build unix/sam
输出的二进制文件名为 'sam' 或 'sam.exe')命名的输出文件(写入Windows可执行文件时会添加.exe
后缀);编译多个包或单个非main包时,build会编译包,但会丢弃生成的对象,仅用于检查包是否可编译
删除对象文件和缓存文件 用法如下
go clean [clean flags] [build flags] [packages]
clean从包源目录中删除对象文件。go命令在一个临时目录中构建大多数对象,因此go clean主要关注其他go工具或通过手动调用go build
留下的对象文件
展示包或符号的文档 用法
go doc [-u] [-c] [package|[package.]symbol[.methodOrField]]
go doc <pkg>
go doc <sym>[.<methodOrField>]
go doc [<pkg>.]<sym>[.<methodOrField>]
go doc [<pkg>.][<sym>.]<methodOrField>
// 在所有形式中,当匹配符号时,参数中的小写字母与任意一个大写字母都匹配,
// 但大写字母完全匹配。这意味着,如果不同的符号有不同的大小写,则包中的小写参数可能有多个匹配项。如果出现这种情况,则打印所有匹配的文档
## 例子
go doc 展示当前包的文档
go doc Foo 展示当前包中Foo的文档(Foo为首字母大写,因此不会匹配包路径)
go doc encoding/json 展示encoding/json包文档
go doc json encoding/json缩写形式
go doc json.Number (或 go doc json.number) 展示json.Number的文档和方法摘要
go doc json.Number.Int64 (或 go doc json.number.int64) 展示json.Number中Int64方法的文档
go doc cmd/doc 显示doc命名的包文档
go doc -cmd cmd/doc 在doc命令中显示包文档和导出的符号
go doc template.new 展示html/template中New函数的文档
go doc text/template.new 一个参数,展示text/template中New函数的文档
go doc text/template new 两个参数,展示text/template中New函数的文档
打印go环境信息 用法
go env [-json] [-u] [-w] [var ...]
默认情况下,env将信息打印为shell脚本(在windows上,是批处理文件)。如果一个或多个变量名作为参数给定,env将在其自己的行上打印每个命名变量的值
更新包以使用新的APIs 使用方法
go fix [packages]
fix对由导入路径命名的包运行go fix命令。fix查找使用旧api的go程序,并重写它们以使用新的api; 更新到新的go版本后,fix将帮助您对程序进行必要的更改。使用
go tool fix [-r name,...] [path ...]
如果没有显式路径,fix将读取标准输入并将结果写入标准输出; 如果命名路径是一个文件,fix会就地重写命名文件; 如果命名路径是一个目录,fix重写该目录中的所有.go文件树
gofmt(重新格式化)源码包 使用方法
go fmt [-n] [-x] [packages]
fmt在由导入路径命名的包上运行命令go fmt -l -w
,它打印被修改文件的名称
-n标志打印将要执行的命令; -x标志在执行命令时打印命令
要了解更多关于gofmt细节可以运行命令go doc cmd/gofmt
通过处理源码生成go文件 使用方法
go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]
生成(必须显示运行)由现有文件中的指令描述的运行命令。这些命令可以运行任何进程,但其意图是创建或更新go源文件。它还接受标准的构建标志,包括-v,-n和-x: -v标志在处理过程中打印包和文件的名称; -n标志打印将要执行的命令; -x标志在执行命令时打印命令
将依赖项添加到当前模块并安装它们 使用方法
go get [-d] [-t] [-u] [-v] [-insecure] [build flags] [packages]
get解析并向当前开发模块添加依赖项,然后构建并安装它们
第一步,要解决添加哪些依赖项 对于每个命名的包或包模式,get必须决定使用相应模块的哪个版本。默认情况下,get会查找最新的标记版本,如v0.4.5或v1.2.3; 如果没有标记的发布版本,get将查找最新的标记的预发布版本,如v0.0.1-pre1; 如果根本没有标记的版本,get将查找最新的已知提交。如果在更高版本(例如,比最新版本更新的预发行版)中还不需要该模块,则get将使用它查找的版本。否则,get将使用当前所需的版本
第二步是下载(如果需要)、构建和安装命名包 如果参数命名的是模块而不是包(因为模块的根目录中没有go源代码),则会跳过该参数的安装步骤,而不会导致构建失败
编译安装包和依赖项 使用方法
go install [-i] [build flags] [packages]
可执行文件安装在由GOBIN环境变量命名的目录中,如果未设置GOPATH环境变量,则默认为HOME/go/bin; GOROOT/bin或GOBIN中
禁用module-aware模式时,其他软件包将安装在目录GOOS_$GOARCH中; 启用module-aware模式时,将构建并缓存其他包,但不安装。-i标志还安装命名包的依赖项
列出包或模块 使用方法
go list [-f format] [-json] [-m] [list flags] [build flags] [packages]
list列出了命名包,每行一个。最常用的标志是-f和-json,它们控制为每个包打印的输出的形式。-f标志
使用包模板的语法指定列表的备用格式,传递给模板的结构形如
type Package struct {
Dir string // 包含包源代码的目录
ImportPath string // 包在目录中的导入路径
ImportComment string // package语句的import注释中的路径
Name string // 包名称
Doc string // 包文档字符串
Target string // 安装路径
Shlib string // 包含此包的共享库(仅在-linkshared时设置)
Goroot bool // 这个包在GOROOT目录下吗?
Standard bool // 这个包是标准go库的一部分吗?
Stale bool // `go install`对这个包有什么作用码?
StaleReason string // explanation for Stale==true
Root string // 包含这个包的GOROOT或GOPATH目录
ConflictDir string // $GOPATH中的这个目录shadows dir
BinaryOnly bool // binary-only package (no longer supported)
ForTest string // package is only for use in named test
Export string // file containing export data (when using -export)
Module *Module // info about package's containing module, if any (can be nil)
Match []string // command-line patterns matching this package
DepOnly bool // package is only a dependency, not explicitly listed
// Source files
GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
CgoFiles []string // .go source files that import "C"
CompiledGoFiles []string // .go files presented to compiler (when using -compiled)
IgnoredGoFiles []string // .go source files ignored due to build constraints
CFiles []string // .c source files
CXXFiles []string // .cc, .cxx and .cpp source files
MFiles []string // .m source files
HFiles []string // .h, .hh, .hpp and .hxx source files
FFiles []string // .f, .F, .for and .f90 Fortran source files
SFiles []string // .s source files
SwigFiles []string // .swig files
SwigCXXFiles []string // .swigcxx files
SysoFiles []string // .syso object files to add to archive
TestGoFiles []string // _test.go files in package
XTestGoFiles []string // _test.go files outside package
// Cgo directives
CgoCFLAGS []string // cgo: flags for C compiler
CgoCPPFLAGS []string // cgo: flags for C preprocessor
CgoCXXFLAGS []string // cgo: flags for C++ compiler
CgoFFLAGS []string // cgo: flags for Fortran compiler
CgoLDFLAGS []string // cgo: flags for linker
CgoPkgConfig []string // cgo: pkg-config names
// Dependency information
Imports []string // import paths used by this package
ImportMap map[string]string // map from source import to ImportPath (identity entries omitted)
Deps []string // all (recursively) imported dependencies
TestImports []string // imports from TestGoFiles
XTestImports []string // imports from XTestGoFiles
// Error information
Incomplete bool // this package or a dependency has an error
Error *PackageError // error loading package
DepsErrors []*PackageError // errors loading dependencies
}
下面记录的其他列表标志控制更具体的细节
模块维护 go mod提供对模块操作的访问,使用方法如下所示
go mod <command> [arguments]
注意,所有go命令都内置了对模块的支持,而不仅仅是“go mod”。例如,日常添加、删除、升级和降级依赖项都应该使用“go get”完成。command列表如下
下载模块到本地缓存 使用方法如下
go mod download [-json] [modules]
下载命名模块,可以是选择主模块依赖项的模块模式,也可以是path@version格式的模块查询。如果没有参数,download将应用于主模块的所有依赖项
go命令将在正常执行期间根据需要自动下载模块。“go mod download”命令主要用于预填充本地缓存或计算go模块代理
从工具或脚本编辑go.mod 使用方法如下
go mod edit [editing flags] [go.mod]
编辑提供了一个用于编辑go.mod的命令行接口,主要用于工具或脚本。它只读取go.mod,不查找有关模块的信息。默认情况下,edit读取和写入主模块的go.mod文件,但可以在编辑标志后指定其他目标文件。编辑标志指定一些列编辑操作
打印模块需求图 使用方法如下
go mod graph
图以文本形式打印模块需求图(应用的替换)。输出中的每一行都有两个空格分隔的字段:一个模块及其一个需求。每个模块都被标识为path@version格式的字符串,但主模块没有@version后缀
在当前目录下初始化新的模块 使用方法
go mod init [module]
init初始化并将新go.mod写入当前目录,实际上创建一个新的模块,该模块以当前目录为根
添加缺失的模块并移除未使用的模块 使用方法如下
go mod tidy [-v]
tidy确保go.mod与模块中的源代码匹配。它增加了构建当前模块的包和依赖项所需的任何缺少的模块,并且移除未使用的模块。它还将添加任何缺少项的go.sum并删除任何不必要的项
-v标志导致tidy将有关已删除模块的信息打印到标准错误
生成依赖项的自动生成副本 使用说明
go mod vendor [-v]
vendor重置主模块的vendor目录,以包含构建和测试所有主模块包所需的所有包。它不包括vendored的测试代码
-v标志将vendor提供的模块和包的名称打印为标准错误
验证依赖项是否具有预期内容 使用说明
go mod verify
验证检查当前模块(存储在本地下载的源缓存中)的依赖项在下载后是否未被修改。如果所有模块都未修改,验证打印“all modules verified.”,否则它报告哪些模块已被更改,并导致“go mod”以非零状态退出
解释为什么需要包或模块 使用说明
go mod why [-m] [-vendor] packages...
why在导入图中显示从主模块到列出的每个包的最短路径。如果给定了-m标志,why将参数视为模块列表,并在每个模块中找到指向任何包的路径。默认情况下,why查询与“go list all”匹配的包的graph,其中包括可访问包的测试。-vendor标志导致排除依赖项测试的原因
编译并运行go程序 使用说明
go run [build flags] [-exec xprog] package [arguments...]
run编译并运行名为main的go包。通常,包被指定为来自单个目录的.go源文件列表,但它也可能是与单个已知包匹配的导入路径、文件系统路径或模式,如“go run.”或“go run my/cmd”
默认情况下,“go run”直接运行编译后的二进制文件:“a.out arguments…”。如果给定了-exec标志,“go run”使用xprog调用二进制文件xprog a.out arguments...
测试包 使用说明
go test [build/test flags] [packages] [build/test flags & test binary flags]
go test
重新编译每个包以及名称与文件模式*_test.go
匹配的任何文件。这些附加文件可以包含test functions、benchmark functions和example functions。每个列出的包都会导致执行单独的测试二进制文件。文件名以_
开头的文件(包括_test.go
)或.
被忽略
用后缀_test
声明包的测试文件将被编译为单独的包,然后与主测试二进制连接并运行。go工具将会忽略名为testdata
的目录,使其可以保存测试所需的辅助数据
go test的两种不同运行模式
- 本地目录模式,在没有包参数(例如,“go test”或“go test-v”)的情况下调用go test时发生。在此模式下,go test编译当前目录中包的源码和测试文件,然后运行生成的测试二进制文件。在此模式下,将禁用缓存。在包测试完成后,go测试打印一个显示测试状态的“摘要行”(“OK”或“FAIL”)、包名和测试的时间
- 包列表模式,在使用显式包参数(例如“go test math”、“go test ./…”、“go test”)调用go test时发生。在此模式下,go test编译并测试命令行中列出的每个包。如果包测试通过,则go测试只打印最终的“OK”摘要行。如果包测试失败,go test将打印完整的测试输出。如果使用-bench或-v标志调用,go测试打印完整的输出,甚至通过传递包测试,以便显示请求的基准测试结果或冗长日志记录。所有列出的包测试完成并打印输出后,如果存在任何一个包测试失败,go test将打印最终“FAIL”状态
仅在包列表模式下,go test缓存成功的包测试结果,以避免不必要的重复运行测试。当测试结果可以从缓存中恢复时,go test将重新显示以前的输出,而不是再次运行测试二进制文件。当发生这种情况时,go测试打印(缓存)代替汇总行中测试花费的时间
运行特定的go工具 使用方式说明
go tool [-n] command [args...]
tool运行由参数标识的go tool命令,-n标志不带参数地打印已知工具的列表
go版本信息 使用说明
go version [-m] [-v] [file ...]
go version报告用于构建每个可执行文件的go版本。如果命令行中没有命名文件,则go version将打印其自己的版本信息; 如果目录被命名,go version将遍历该目录,递归地查找识别的go二进制文件并报告它们的版本。默认情况下,go version不会报告在目录扫描期间发现的无法识别的文件
-v标志 报告无法识别的文件
-m标志 go version在可用时打印每个可执行文件的嵌入模块版本信息。在输出中,模块信息由版本行后面的多行组成,每行由一个前导制表符缩进
报告包中可能出现的错误 使用方法说明
go vet [-n] [-x] [-vettool prog] [build flags] [vet flags] [packages]
vet对由导入路径命名的包运行go vet命令
构建模式
go build
和go install
命令采用-buildmode参数,该参数指示要生成哪种类型的对象文件。当前支持的值为
环境变量
go命令及其调用的工具用于配置参考环境变量。如果环境变量未设置,则go命令使用合理的默认设置。要查看变量<NAME>的有效设计可以运行go env <NAME>
; 要更改变量<NAME>的默认设计,运行命令go env -w <NAME>=<VALUE>
通用环境变量
用于cgo的环境变量
特定于体系结构的环境变量
特殊用途的环境变量
go env
中提供但未从环境中读取的其他信息
逻辑和性能诊断工具
go生态系统提供了大量的API和工具来诊断go程序中的逻辑和性能问题,这一节是对这些可用工具的总结
诊断解决方案可以分为以下几类
- 性能分析 这类工具用于分析go程序的复杂性和成本,例如通过它的内存使用和频繁调用的函数来标识go程序的开销部分
- 追踪 是一种在调用或用户请求的整个生命周期中检测代码以分析延迟的方法,它提供了每个组件对系统的总延迟概述,可以跨越多个go进程进行
- 调试 允许我们暂停go程序并检查其执行。程序状态和流程可以通过调试来验证
- 运行时统计和事件 运行时统计和事件的收集和分析为go程序的健康提供了高层次的概述。尖峰/度量的监控指标有助于识别吞吐量、利用率和性能的变化
Tips 一些诊断工具可能相互干扰。例如,精准内存剖析可能影响CPU性能分析的准确性、goroutine阻塞分析会影响调度器跟踪。因此,单独使用工具获取更精确的信息
性能分析 对于识别昂贵的或频繁调用的代码段非常有用。go运行时以pprof可视化工具提供所期望格式的性能分析数据。在测试期间,也可以通过go test或net/http/pprof包中提供的endpoints来收集性能分析数据
由runtime/pprof预定义配置文件
- cpu 决定了程序在actively状态(而不是在sleeping或waiting I/O)时花费的cpu时间
- heap 报告内存分配示例;用于监视当前和历史内存使用情况,并检查内存泄漏
- threadcreate 报告程序中引导创建新线程的部分
- goroutine 报告当前所有goroutine的堆栈跟踪
- block 显示goroutine阻塞等待同步原语(包括timer channels),block profile默认为未启用状态,使用runtime.SetBlockProfileRate可以启用它
- mutex 报告锁争用。当您认为由于互斥争用导致CPU未充分利用时,请使用此profile。默认情况下mutex profile处于未启用状态,通过runtime.SetMutexProfileFraction可以启用它
其他分析器 在Linux上,可以使用perf工具分析go程序,perf可以配置和解开cgo/SWIG代码和内核,因此可以深入了解native/kernel性能瓶颈; 在MacOS上,可以使用Instruments分析go程序
生产服务性能分析 分析生产中的程序是安全的,但是启用某些profile(例如CPU profile)会增加成本。您可能想要定期分析生产服务性能问题,特别是在具有单个进程的多个副本的系统中,周期性地随机挑选一个副本是安全的选择。选择一个生产进程,每隔Y秒分析并保存它的结果以进行可视化分析;然后定期重复。可以手动和/或自动检查结果以发现问题。性能收集可能相互干扰,因此建议每次只收集单个概要文件
可视化数据分析方法 go使用go tool pprof
工具提供text、graph和callgrind可视化
自定义profile go用户可以通过运行时提供的pprof.Profile创建他们的自定义配置文件,并使用现有的工具来检查它们。如下示例将监听7777端口并以 /custom_debug_path/profile
endpoint,为pprof.Profile提供服务
package main
import (
"log"
"net/http"
"net/http/pprof"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/custom_debug_path/profile", pprof.Profile)
log.Fatal(http.ListenAndServe(":7777", mux))
}
追踪 这是一种在调用链的整个生命周期中检测代码以分析时延的方法,go提供golang.org/x/net/trace包作为每个go节点的最小跟踪后端,并用一个简单的dashboard提供一个最小的检测库,go还提供了一个可执行的Tracer来追踪间隔期间内运行时事件。追踪可以为我们提供
- 检测并分析go进程中的应用程序延迟
- 在一个很长的调用链中测量特定调用的成本
- 找出利用率并改进性能。没有跟踪数据,瓶颈并不总是显而易见
在单体系统中,从程序的构建块收集诊断数据相对容易,所有模块都在一个进程中,并共享公共资源来报告日志、错误和其他诊断信息。一旦系统由单体进程扩展到分布式微服务,就很难定位从前端Web服务器到所有后台的调用,以及响应返回给用户。这也是分布式追踪在测试和分析生产系统方面发挥重要作用的地方
分布式追踪是一种在用户请求的整个生命周期中检测代码以分析延迟的方法。当系统是分布式的,并且传统的分析和调试工具无法扩展时,您可能希望使用分布式跟踪工具来分析用户请求和RPC的性能。分布式追踪系统是我们能够
- 在大型系统中检测并分析应用程序延迟
- 跟踪用户请求生命周期内的所有RPC,并查看仅在生产中可见的集成问题
- 找出可以应用于我们系统的性能改进。在跟踪数据收集之前,许多瓶颈是不明显的
go生态系统为每个追踪系统提供了不同的分布式跟踪库和对后端透明的库
调试 调试是识别程序错误行为的过程,调试器允许我们了解程序的执行流程和当前状态。go用户主要使用以下调试器
- **Delve ** 作为go编程语言的调试器,它支持go的运行时概念和内置类型。Delve正试图成为一个功能齐全的可靠的go程序调试器
- GDB go通过标准go编译器和gccgo提供GDB支持。堆栈管理、线程和运行时包含不同于执行模型的方面,GDB可能混淆调试器,即使程序是用gccgo编译的。尽管GDB可以用来调试go程序,但它并不理想,可能会造成混乱
运行时统计和事件 运行时提供用户内部事件的统计和报告,以便在运行时级别诊断性能和使用问题。用户可以监视这些统计信息,以便更好地了解go程序的整体健康和性能。一些经常监视的统计数据和状态
- runtime.ReadMemStats 报告与堆分配和垃圾收集相关的度量指标。内存统计对于监视进程消耗多少内存资源、进程是否可以充分利用内存以及捕获内存泄漏是有用的
- debug.ReadGCStats 读取垃圾收集的统计信息。查看gc暂停上花费了多少资源是很有用的。它还报告了垃圾收集器暂停和暂停时间百分比的时间线
- debug.Stack 返回当前堆栈跟踪,堆栈跟踪对于查看当前正在运行的goroutine的数量、它们正在执行的操作以及它们是否被阻止非常有用
- debug.WriteHeapDump 暂停所有goroutine的执行并允许您将堆转储到文件。堆转储是在给定时间内go进程内存的快照。它包含所有分配的对象以及goroutine、finalizers等
- runtime.NumGoroutine 返回当前goroutine的数目。可以监视该值以查看是否有足够的goroutine供使用,或检测goroutine泄漏
go附带运行时Execution Tracer来捕获大量运行时事件。调度、SysCall、垃圾回收、堆大小和其他事件由运行时收集,并可用于go工具跟踪可视化。Tracer可用于
- 了解goroutine如何执行
- 了解一些核心运行时事件,例如GC
- 识别并行性差的执行
小结
go提供了丰富的命令行和工具,在日常运维开发中熟练使用命令/工具能够大大提升效率。本文是关于命令行和常用工具的简单总结,希望能对您有所帮助