GO开发技巧
1. 设置GO语言vim开发环境
在vim中开发GO最好安装相关的插件,比如vim-go这个插件。这个插件除了提供格式化、语法高亮、语法检测等功能以外还有很多方便的功能。
编译命令,对应go build:
:GoBuild
安装,对应go install:
:GoInstall
测试,对应go test:
:GoTest
运行一个单独测试:
:GoTestFunc
覆盖率:
:GoCoverage
运行当前程序,对应go run:
:GoRun
goto符号定义:
:GoDef
文档查询:
:GoDoc
:GoDocBrowser
添加/删除包引用:
:GoImport
:GoDrop
设置GOPATH:
:GoPath
在结构体增加/删除tag:
:GoAddTags
:GoRemoveTags
静态语法检查:
:GoMetaLinter // 调用gometalinter
:GoLint // 调用golint
高级代码分析:
:GoImplements
:GoCallees
:GoReferrers
重命名:
:GoRename
在vim中查询vim-go的帮助文档:
:help vim-go
安装完成后打开vim,运行”:GoInstallBinaries”安装依赖的工具。
再安装其它依赖工具:
// gocode is used by many editors to provide intellisense
go get github.com/nsf/gocode
// goimports is something you should run when saving code to fill in import paths
go get golang.org/x/tools/cmd/goimports
// gorename is used by many editors to provide identifier rename support
go get golang.org/x/tools/cmd/gorename
// oracle is a tool that help with code navigation and search
go get golang.org/x/tools/cmd/oracle
// golint should be run after every build to check your code
go get github.com/golang/lint/golint
2. 其它常用工具
文件格式化
gofmt <file>
打印package信息
查询当前目录模块信息:
go list
查询指定模块:
go list <module>
常用命令:
go list -f '{{ .Name }}' go list -f '{{ .Name }}: {{ .Doc }}' go list -f '{{ .Imports }}' // 结果用中括号输出 $ go list -f '{{.Imports}}' fmt [errors io math os reflect strconv sync unicode/utf8] go list -f '{{ join .Imports "\n"}}' // 结果用换行输出 $ go list -f '{{join .Imports "\n"}}' fmt errors io math os reflect strconv sync unicode/utf8
跨平台编译:
GOOS=windows go build
查询文档
查询当前模块:
go doc
查询指定模块:
go doc \<module\> go doc \<module\> [function]
在线文档:
godoc -http :8080
程序错误查询
程序执行的时候有些情况下不会打印错误信息,因为go中没有exception,当错误出现时是通过返回error来捕捉错误信息,如果程序执行的时候没有捕捉错误信息,那么就会出现这种状况。对于这种状况可以通过命令”errcheck”来获得错误信息。
命令:
errcheck
go vet工具
go vet工具用来检查程序中可能的错误。
3. 测试
如何添加测试
通常在被测试的程序文件同目录下添加’_test.go’结尾的文件,例如当要测试’program.go’时在同一个目录下添加’program_test.go’文件。
接下来是在’program_test.go’文件中添加测试代码。测试文件需要引入’testing’包。接下来是编写测试函数,测试函数需要’Test’字符开头,注意必须是大写’T’开头的’Test’。
例如:
import "testing"
func TestSomeFunction(t *testing.T) {
// do some test here
}
table driven test
go测试推荐’table drive test’的方法,其实是一种编程技巧,使用这种方法可以在一定程度上简化测试代码。
这种测试方法其实是将测试的输入/输出作为测试数据写在一个结构体内,并在测试代码中使用,写个简单的例子,比如说要测试一个简单的’sum’函数。
func sum(a int, b int) int {
return (a+b)
}
测试代码:
// you're defining the test table here
var testCases = []struct {
a int
b int
result int
}{
{1, 2, 3},
{3, 5, 8},
}
// test code
func TestSum(t *testing.T) {
for _, tc := range testCases {
r := sum(tc.a, tc.b)
if r != tc.result {
t.Errorf("Failed case: param[%d, %d], result[%d], expected[%d]", tc.a, tc.b, r, tc.result)
}
}
}
stdout重定向测试
关于stdout重定向测试并不是一个测试的重点,只是有时候你写的一个函数需要输出一些字符到标准输出stdout上,比如使用fmt.Println(),如果此时恰好需要测试程序检测这种情况,那么这种技巧就可以派上用场了。
比如有下面这样一段程序:
func isNegative(i int) {
if i < 0 {
fmt.Println("Negative")
} else {
fmt.Println("Non-negative")
}
}
这个程序的测试可以这样写:
func captureStdoutWithParam(f func(p int), p int) string {
// save the original stdout
oldStdout := os.Stdout
// create pipe to redirect the stdout to 'r'
r, w, _ := os.Pipe()
os.Stdout = w
f(p)
w.Close()
// restore the stdout
os.Stdout = oldStdout
out, _ := ioutil.ReadAll(r)
return string(out)
}
func TestIsNegative(t *testing.T) {
cases := []struct {
input int
output string
}{
{-3, "Negative"},
{0, "Non-negative"},
{5, "Non-negative"},
}
for _, c := range cases {
out := captureStdoutWithParam(isNegative, c.input)
if !strings.Contains(out, c.output) {
t.Errorf("Expected [%s], get[%s]", c.output, out)
}
}
}
4. debug
go语言debug有几个选项:
gdb
关于gdb的使用go的官方文档似乎并不推荐。
This applies to the standard toolchain (the gc Go compiler and tools). Gccgo has native gdb support. Besides this overview you might want to consult the GDB manual.
GDB does not understand Go programs well. The stack management, threading, and runtime contain aspects that differ enough from the execution model GDB expects that they can confuse the debugger, even when the program is compiled with gccgo. As a consequence, although GDB can be useful in some situations, it is not a reliable debugger for Go programs, particularly heavily concurrent ones. Moreover, it is not a priority for the Go project to address these issues, which are difficult. In short, the instructions below should be taken only as a guide to how to use GDB when it works, not as a guarantee of success.
godebug
在godebug的github上也表明这个工具已经过时了,并且推荐使用’delve’。
DEPRECATED! There will be no further development. Please use https://github.com/derekparker/delve. But if you want to keep the project going and ready to become its maintaner please contact us and we can make you one.
delve
安装
参考github文档中的安装方法。
方法一:
$ brew install go-delve/delve/delve
方法二:
$ xcode-select --install $ go get -u github.com/derekparker/delve/cmd/dlv
接下来就可以使用dlv进行debug了。
$ dlv --help
Delve is a source level debugger for Go programs.
Delve enables you to interact with your program by controlling the execution of the process,
evaluating variables, and providing information of thread / goroutine state, CPU register state and more.
The goal of this tool is to provide a simple yet powerful interface for debugging Go programs.
Pass flags to the program you are debugging using `--`, for example:
`dlv exec ./hello -- server --config conf/config.toml`
Usage:
dlv [command]
Available Commands:
attach Attach to running process and begin debugging.
connect Connect to a headless debug server.
core Examine a core dump.
debug Compile and begin debugging main package in current directory, or the package specified.
exec Execute a precompiled binary, and begin a debug session.
help Help about any command
run Deprecated command. Use 'debug' instead.
test Compile test binary and begin debugging program.
trace Compile and begin tracing program.
version Prints version.
Flags:
--accept-multiclient Allows a headless server to accept multiple client connections. Note that the server API is not reentrant and clients will have to coordinate.
--api-version int Selects API version when headless. (default 1)
--backend string Backend selection:
default Uses lldb on macOS, native everywhere else.
native Native backend.
lldb Uses lldb-server or debugserver.
rr Uses mozilla rr (https://github.com/mozilla/rr).
(default "default")
--build-flags string Build flags, to be passed to the compiler.
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "localhost:0")
--log Enable debugging server logging.
--wd string Working directory for running the program. (default ".")
Use "dlv [command] --help" for more information about a command.