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.