Go的工程管理

您可以在这里读到这篇文章最新状态:

http://www.lijiaocn.com/blog/2014/07/23/Go的工程管理.html

创建时间: 2014/07/23 10:16:39 修改时间: 2014/07/23 14:09:57 作者:lijiao


摘要

Go自身提供了很好的工程化管理, 几乎不依赖IDE, 大赞。

下面涉及Go的环境搭建(linux)、代码编辑器(vim)、源码管理、单元测试框架、单元性能测试(benchmark)。

环境搭建

安装go开发套件

下载安装文件go1.3.linux-amd64.tar.gz, 解压到/opt

在.bashrc中添加:

export GOROOT=/opt/go        #go install dir

export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

(可选)配置VIM

将/opt/go/misc/vim中内容复制到.vim/bundle/go中(vim插件安装), 包含以下功能:

:Godoc      //显示光标所在位置的内容的godoc

创建go模板文件, ~/.vim/template/template.go (需要安装有vim template插件):

:% s/ctime/\=strftime("%Y\/%m\/%d %H:%M:%S")/ge
:% s/ltime/\=strftime("%Y\/%m\/%d %H:%M:%S")/ge
:% s/year/\=strftime("%Y")/ge
//Copyright year. All rights reserved.
//Author: lja  
//Createtime: ctime  Lastchange:ltime
//changlog:  1. create by lja

package

workspace

设置workspace:

export GOPATH=/opt/example
export PATH=$PATH:$GOPATH/bin

mkdir -p $GOPATH/src
mkdir -p $GOPATH/bin
mkdir -p $GOPATH/pkg

第一个执行程序

$GOPATH/src/hello/hello.go

//Copyright 2014. All rights reserved.
//Author: lja  
//Createtime: 2014/07/23 06:28:50  Lastchange:2014/07/23 06:28:50
//changlog:  1. create by lja

package main

import (
|   "fmt"
)

func main() {
|   fmt.Printf("Hello world!\n")
}

编译、安装:

go install hello    //注意目标目录的表示方法: 从src/hello/hello.go中去掉了src和hello.go

在$GOPATH/bin目录下生成程序hello:

[lja@localhost bin]$ pwd
/opt/example/bin
[lja@localhost bin]$ ls
hello

注意如果设置了环境变量GOBIN, hello程序将被安装到GOBIN所指的目录

第一个程序库(library)

创建目录:

mkdir $GOPATH/src/hellopkg

创建文件, $GOPATH/src/hellopkg/hellopkg.go

//Copyright 2014. All rights reserved.
//Author: lja  
//Createtime: 2014/07/23 07:10:53  Lastchange:2014/07/23 07:10:53
//changlog:  1. create by lja

package hellopkg  

import (
|   "fmt"
)

func Helloworld(){        //注意首字母是大写,表示可以被外部调用
|   fmt.Printf("Hello world from hellopkg!\n")
}

编译安装:

go install hellopkg

在$GOPATH/pkt目录生成hellopkg.a

[lja@localhost linux_amd64]$ pwd
/opt/example/pkg/linux_amd64
[lja@localhost linux_amd64]$ ls
hellopkg.a

注意: hellopkg.go中隶属的package最好与所在的目录名一致。如果不一致, 在import的时候需要包含目录名, 使用的时候需要使用package名

第一次使用pkg

创建目录:

mkdir $GOPATH/src/hellopkg_use

创建文件, $GOPATH/src/hellopkg/hello_pkg.go

//Copyright 2014. All rights reserved. 
//Author: lja  
//Createtime: 2014/07/23 07:15:07  Lastchange:2014/07/23 07:15:07
//changlog:  1. create by lja

package main

import (
|   "hellopkg"
)

func main() {
|   hellopkg.Helloworld()
}

编译安装:

go install hellopkg_use

在$GOPATH/bin目录下生成程序hellopkg_use:

[lja@localhost bin]$ pwd
/opt/example/bin
[lja@localhost bin]$ ls
hello  hellopkg_use

注意编译后的可执行程序的名称是目录名hellppkt_use, 不是文件名hello_pkg.go中的hello_pkg

通过上面过程可以发现, 如果src的子目录中包含package main, 这个子目录被编译成可执行程序, 否则编译成pkg

第一个远程代码

安装gocode, 远程地址: https://github.com/nsf/gocode

go get -u github.com/nsf/gocode

gocode源码被下载到src

[lja@localhost gocode]$ pwd
/opt/example/src/github.com/nsf/gocode
[lja@localhost gocode]$ ls
autocompletecontext.go  client.go  cursorcontext.go  declcache.go  docs   emacs-company  _gccgo     _goremote  os_posix.go    package.go  ripper.go  scope.go   _testing  vim
autocompletefile.go     config.go  debian            decl.go       emacs  formatters.go  gocode.go  LICENSE    os_windows.go  README.md   rpc.go     server.go  utils.go

gocode程序被编译生成到bin:

[lja@localhost bin]$ ls
gocode  hello  hellopkg_use
[lja@localhost bin]$ pwd
/opt/example/bin
[lja@localhost bin]$ ls
gocode  hello  hellopkg_use

gocode可以使在用vim编辑go程序时给出代码提示, 用法如下:

安装vim插件:

cd $GOPATH/src/github.com/nsf/gocode/vim
./pathogen_update.sh      //里面有三个安装脚本, 根据vim的情况做选择

配置gocode:

gocode set propose-builtins true      //提示go自带的内容
gocode set autobuild true             //自动编译pkg

用vim打开.go文件, 补全时键入Ctrl+x,Ctrl+o, 需要注意只会提示已经被import的pkg中成员。

自动化文档

go的注释可以自动转换成文档。只需将注释写在package、func之前, 中间不能有空行

例如:

//这时一个hellopkt
//你可以用它来输出一行Hello world
package hellopkt


//这是一个helloword函数
func Helloworld(){
        fmt.Printf("Hello world from hellopkg!\n")
}

在代码中这样写入注释后,就可以直接使用godoc查看文档,例如:

[lja@localhost hellopkg]$ godoc hellopkg
PACKAGE DOCUMENTATION

package hellopkg
        import "hellopkg"

        这是一个hellopkt 你可以用它来输出一行Hello world

FUNCTIONS

func Helloworld()
        这时一个Helloworld函数


[lja@localhost hellopkg]$ godoc hellopkg Helloworld
func Helloworld()
        这时一个Helloworld函数

另外,go自身的源码中专门用了一个doc.go文件作为pkg的说明文件,可以借鉴这种方式. 例如/opt/go/src/pkg/fmt/doc.go

/*
    Package fmt implements formatted I/O with functions analogous
    to C's printf and scanf.  The format 'verbs' are derived from C's but
    are simpler.


    Printing

    The verbs:

    General:
        %v  the value in a default format.
            when printing structs, the plus flag (%+v) adds field names
        %#v a Go-syntax representation of the value
        %T  a Go-syntax representation of the type of the value
        %%  a literal percent
    ....
....
*/
package fmt

测试框架

测试源码的命名必须采用如下格式:

Target_test.go    //Target没有要求,建议以文件为单位,每个目标文件file.go对应一个测试文件file_test.go

测试源码必须包含testing, 测试函数必须按照如下格式定义:

func Test函数名(t *testing.T){
}

例如 $GOPATH/src/hellopkg/hellopkg_test.go

//Copyright 2014. All rights reserved.
//Author: lja  
//Createtime: 2014/07/23 09:06:19  Lastchange:2014/07/23 09:06:19
//changlog:  1. create by lja

package hellopkg

import (
|   "testing"
)

func TestHelloworld(t *testing.T) {
|   //t.Errorf("没有什么好测的, 给出个测试不通过的例子")
}                                                            

测试过程:

go test hellopkg     //执行hellopkg包的测试程序
go test              //执行所有测试程序

测试结果如下:

[lja@localhost hellopkg]$ go test hellopkg
--- FAIL: TestHelloworld (0.00 seconds)
                hellopkg_test.go:13: 没有什么好测的, 给出个测试不通过的例子
FAIL
FAIL    hellopkg        0.004s

Benchmark

Benchmark是测试框架的一部分, 用来获得函数的运行效率信息。参考下面的文章:

how-to-write-benchmarks-in-go

在$GOPATH/src/hellopkg/hellopkg.go中添加函数Multi:

func Multi(n int, m int)int{ 
        return n*m 
}  

在$GOPATH/src/hellopkg/hellopkg_test.go中添加Benchmark测试代码:

func BenchmarkMulti(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Multi(88,99)
    }

执行test,并执行Benchmark

//-bench参数正则匹配要执行的benchmark函数
[lja@localhost hellopkg]$ go test hellopkg -bench=BenchmarkMulti 
PASS
BenchmarkMulti  2000000000               1.04 ns/op
ok      hellopkg        2.211s

如果test没有通过, 后续的benchmark测试也不会执行

不执行test, 只执行Benchmark

//-run参数正则匹配要执行的test函数, 这里随便写一个XXX, 使正则匹配结果为空
[lja@localhost hellopkg]$ go test hellopkg -run=XXX -bench=BenchmarkMulti
PASS
BenchmarkMulti  2000000000               1.09 ns/op
ok      hellopkg        2.311s

文献

  1. http://xxx "Name"