一、go 简要说明

一、go 环境变量

GOROOT

该环境变量的值为Go语言的安装目录。如:
export GOROOT=/usr/local/go

GOPATH

Go语言工作区间集合。如:
export GOPATH=~/golib:~/goproject

GOBIN

存放Go程序可执行文件的目录。如:
export GOBIN=~/gobin

PATH

为了方便使用Go语言命令和Go程序的可执行文件,需要追加其值。如:export PATH=$PATH:$GOROOT/bin:$GOBIN

二、工作区和GOPATH

工作区结构参考

/home/mxy/golib:
	src/
	pkg/
	bin/
src 目录

主要用来存放源码文件,使用代码包的组织方式。

源码文件说明

源码文件分为命令源码文件、库源码文件、测试源码文件

  1. 命令源码文件

声明自己属于main代码包、包含无参数声明和结果声明的main函数
被安装后,相应的可执行文件会被存放到GOBIN指向的目录或者<当前工作区目录>/bin下
go build命令安装

  1. 库源码文件

不具备命令源码文件的两个特征的源码文件
被安装后,相应的归档文件会被存放到<当前工作区目录>/pkg/<平台相关目录> 下
go install 命令安装

  1. 测试源码文件

不具备命令源码文件的那两个特征的源码文件
名称以_test.go为后缀,其中至少有一个Test或者Benchmark前缀的方法,并且接收一个类型为testing.T或者testing.B的参数。如:

func TestHelloWorld(t *testing.T) {
	t.Log("hello world")
}

或者

func BenchmarkTest(b *testing.B) {
	b.Log("hello world")
}
pkg目录

用于存放归档文件(名称以.a为后缀的文件)
所有归档文件都会被存放到该目录下的平台相关目录中,同样以代码包为组织形式

平台相关

go包含两个隐藏的环境变量:GOOS 和 GOARCH
以$GOOS $GOARCH为命名方式,如linux_amd64
<工作区目录>/pkg/<平台相关目录>/<一级代码包>/<二级代码包>/<末级代码包>.a

bin目录

用于存放当前工作区中的Go程序的可执行文件

  1. 当环境变量GOBIN已经有效设置时,该目录被忽略。
    2.当GOPATH包含多个工作区的路径时,必须设置GOBIN,否则无法安装Go程序的可执行文件。

三、代码包

代码包规则

一个代码包实际上就是一个由导入路径代表的目录
导入路径就是<工作区目录>/src或者<工作区目录>/pkg/<平台相关目录之下的某段子路径。如:
代码包wondertek.portainer就对应于/home/mxy/golib/src/wondertek.portainer目录,其中/home/mxy/golib是一个工作区目录。

代码包声明和导入

代码包声明语句中的包名称应该是导入路径的最右侧子路径
如:wondertek.portainer/utils,导入时候就是package utils

代码包导入语句中使用的包名应该和其导入路径保持一致,如
声明:

    "fmt"
	"pipeline"
	"os"
	"bufio"

导入

import (
	"fmt"
	"pipeline"
	"os"
	"bufio"
) 
别名导入
导入:
import os2 "os"
使用:
os2.Create(filename)
本地化导入
导入:
import . "os"
使用:
Create(filename)
仅仅初始化
导入:
import _ "os"

代码导入会首先对所有全局变量进行求值,然后再执行所有init函数,
被依赖的先执行。

四、命令简介

go run

内部逻辑:先编译源码文件,然后在运行
go run src/demo/demo.go

go build

安装命令源代码
常用参数

-o 
指定输出的文件名,可以带上路径,例如 go build -o a/b/c

-i 
安装相应的包,编译+go install

-a 
更新全部已经是最新的包的,但是对标准包不适用

-n 
把需要执行的编译命令打印出来,但是不执行,这样就可以很容易的知道底层是如何运行的

-p n 
指定可以并行可运行的编译数目,默认是CPU数目

-race 
开启编译的时候自动检测数据竞争的情况,目前只支持64位的机器

-v 
打印出来我们正在编译的包名

-work 
打印出来编译时候的临时文件夹名称,并且如果已经存在的话就不要删除

-x 
打印出来执行的命令,其实就是和-n的结果类似,只是这个会执行

-ccflags 'arg list' 
传递参数给5c, 6c, 8c 调用

-compiler name 指定相应的编译器,gccgo还是gc

-gccgoflags 'arg list' 传递参数给gccgo编译连接调用

-gcflags 'arg list' 
传递参数给5g, 6g, 8g 调用

-installsuffix suffix 为了和默认的安装包区别开来,采用这个前缀来重新安装那些依赖的包,-race的时候默认已经是-installsuffix race,大家可以通过-n命令来验证
	
-ldflags 'flag list'
    '-s -w': 压缩编译后的体积
    -s: 去掉符号表
    -w: 去掉调试信息,不能gdb调试了
    
-linkshared
    链接到以前使用创建的共享库
    -buildmode=shared.
    
-pkgdir dir
    从指定位置,而不是通常的位置安装和加载所有软件包。
    当使用非标准配置构建时,使用-pkgdir将生成的包保留在单独的位置

-tags 'tag list'
    构建出带tag的版本.
    
-toolexec 'cmd args'
  a program to use to invoke toolchain programs like vet and asm.
	For example, instead of running asm, the go command will run
	'cmd args /path/to/asm <arguments for asm>'.
交叉编译
  1. Mac 下编译 Linux 和 Windows 64位可执行程序
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
  1. Linux 下编译 Mac 和 Windows 64位可执行程序
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
  1. Windows 下编译 Mac 和 Linux 64位可执行程序
SET CGO_ENABLED=0
SET GOOS=darwin
SET GOARCH=amd64
go build main.go 

SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build main.go

GOOS:目标平台的操作系统(darwin、freebsd、linux、windows)
GOARCH:目标平台的体系架构(386、amd64、arm)

交叉编译不支持 CGO(它允许 Go 程序与 C 的类库交互操作),所以要禁用它
上面的命令编译 64 位可执行程序,你当然应该也会使用 386 编译 32 位可执行程序

go clean

这个命令是用来移除当前源码包和关联源码包里面编译生成的文件。这些文件包括

_obj/            旧的object目录,由Makefiles遗留
_test/           旧的test目录,由Makefiles遗留
_testmain.go     旧的gotest文件,由Makefiles遗留
test.out         旧的test记录,由Makefiles遗留
build.out        旧的test记录,由Makefiles遗留
*.[568ao]        object文件,由Makefiles遗留

DIR(.exe)        由go build产生
DIR.test(.exe)   由go test -c产生
MAINFILE(.exe)   由go build MAINFILE.go产生
*.so             由 SWIG 产生

参数介绍

-i 清除关联的安装的包和可运行文件,也就是通过go install安装的文件
-n 把需要执行的清除命令打印出来,但是不执行,这样就可以很容易的知道底层是如何运行的
-r 循环的清除在import中引入的包
-x 打印出来执行的详细命令,其实就是-n打印的执行版本
$ go clean -i -n
cd /Users/astaxie/develop/gopath/src/mathapp
rm -f mathapp mathapp.exe mathapp.test mathapp.test.exe app app.exe
rm -f /Users/astaxie/develop/gopath/bin/mathapp

go fmt

格式化命令, go fmt命令,其实是调用了gofmt,而且需要参数-w,否则格式化结果不会写入文件。gofmt -w -l src,可以格式化整个项目

gofmt的参数介绍

-l 显示那些需要格式化的文件
-w 把改写后的内容直接写入到文件中,而不是作为结果打印到标准输出。
-r 添加形如“a[b:len(a)] -> a[b:]”的重写规则,方便我们做批量替换
-s 简化文件中的代码
-d 显示格式化前后的diff而不是写入文件,默认是false
-e 打印所有的语法错误到标准输出。如果不使用此标记,则只会打印不同行的前10个错误。
-cpuprofile 支持调试模式,写入相应的cpufile到指定的文件

go install

用于编译并且安装代码包或者源码文件
安装代码包会在<当前工作区目录>/pkg/<平台相关目录> 下生成归档文件
安装命令源文件会被存放到GOBIN指向的目录或者<当前工作区目录/bin下
go install 不添加参数,处理当前目录

go get

从远程仓库拉取代码
代码会被拉取GOPATH的第一个工作区的src下。

常用参数
-d 只下载,不安装
-fix 下载后,先修正,然后编译安装, 修复老版本兼容
-u 利用网络更新已有的代码包及其依赖, 更新操作
-f 只有在你包含了-u参数的时候才有效,不让-u去验证import中的每一个都已经获取了的,这对于本地fork的包特别有用
-t 同时也下载需要为运行测试所需要的包
-v 显示执行的命令

go test

执行这个命令,会自动读取源码目录下面名为*_test.go的文件,生成并运行测试用的可执行文件。输出的信息类似

ok   archive/tar   0.011s
FAIL archive/zip   0.022s
ok   compress/gzip 0.033s
...

默认的情况下,不需要任何的参数,它会自动把你源码包下面所有test文件测试完毕,当然你也可以带上参数,详情请参考go help testflag

常用的参数:

  • -bench regexp 执行相应的benchmarks,例如 -bench=.
  • -cover 开启测试覆盖率
  • -run regexp 只运行regexp匹配的函数,例如 -run=Array 那么就执行包含有Array开头的函数
  • -v 显示测试的详细命令

go tool

go tool下面下载聚集了很多命令,这里我们只介绍两个,fix和vet

  • go tool fix . 用来修复以前老版本的代码到新版本,例如go1之前老版本的代码转化到go1,例如API的变化
  • go tool vet directory|files 用来分析当前目录的代码是否都是正确的代码,例如是不是调用fmt.Printf里面的参数不正确,例如函数里面提前return了然后出现了无用代码之类的。

go generate

这个命令是从Go1.4开始才设计的,用于在编译前自动化生成某类代码。go generatego build是完全不一样的命令,通过分析源码中特殊的注释,然后执行相应的命令。这些命令都是很明确的,没有任何的依赖在里面。而且大家在用这个之前心里面一定要有一个理念,这个go generate是给你用的,不是给使用你这个包的人用的,是方便你来生成一些代码的。

这里我们来举一个简单的例子,例如我们经常会使用yacc来生成代码,那么我们常用这样的命令:

go tool yacc -o gopher.go -p parser gopher.y

-o 指定了输出的文件名, -p指定了package的名称,这是一个单独的命令,如果我们想让go generate来触发这个命令,那么就可以在当然目录的任意一个xxx.go文件里面的任意位置增加一行如下的注释:

//go:generate go tool yacc -o gopher.go -p parser gopher.y

这里我们注意了,//go:generate是没有任何空格的,这其实就是一个固定的格式,在扫描源码文件的时候就是根据这个来判断的。

所以我们可以通过如下的命令来生成,编译,测试。如果gopher.y文件有修改,那么就重新执行go generate重新生成文件就好。

$ go generate
$ go build
$ go test

godoc

在Go1.2版本之前还支持go doc命令,但是之后全部移到了godoc这个命令下,需要这样安装go get golang.org/x/tools/cmd/godoc

很多人说go不需要任何的第三方文档,例如chm手册之类的(其实我已经做了一个了,chm手册),因为它内部就有一个很强大的文档工具。

如何查看相应package的文档呢?
例如builtin包,那么执行godoc builtin
如果是http包,那么执行godoc net/http
查看某一个包里面的函数,那么执行godoc fmt Printf
也可以查看相应的代码,执行godoc -src fmt Printf

通过命令在命令行执行 godoc -http=:端口号 比如godoc -http=:8080。然后在浏览器中打开127.0.0.1:8080,你将会看到一个golang.org的本地copy版本,通过它你可以查询pkg文档等其它内容。如果你设置了GOPATH,在pkg分类下,不但会列出标准包的文档,还会列出你本地GOPATH中所有项目的相关文档,这对于经常被墙的用户来说是一个不错的选择。

其它命令

go还提供了其它很多的工具,例如下面的这些工具

go version 查看go当前的版本
go env 查看当前go的环境变量
go list 列出当前全部安装的package  
	加入标记-e时,即使参数中包含有不完整的代码包,命令也不会提示错误
	代码包结构体中定义的字段很多,但有些时候我们只需要查看其中的一些字段。那要怎么做呢?标记-f可以满足这个需求。如go list -f {{.ImportPath}} xxxx
$ go list -json github.com/portainer/portainer/cli
{
	"Dir": "/Users/csp/go/src/github.com/portainer/portainer/cli",
	"ImportPath": "github.com/portainer/portainer/cli",
	"Name": "cli",
	"Target": "/Users/csp/go/pkg/darwin_amd64/github.com/portainer/portainer/cli.a",
	"Stale": true,
	"StaleReason": "cannot stat install target",
	"Root": "/Users/csp/go",
	"GoFiles": [
		"cli.go",
		"defaults.go",
		"pairlist.go"
	],
	"IgnoredGoFiles": [
		"defaults_windows.go"
	],
	"Imports": [
		"fmt",
		"github.com/portainer/portainer",
		"gopkg.in/alecthomas/kingpin.v2",
		"os",
		"path/filepath",
		"strings",
		"time"
	],
	"Deps": [
		"bufio",
		"bytes",
		"context",
		"encoding/hex",
		"errors",
		"fmt",
		"github.com/alecthomas/template",
		"github.com/alecthomas/template/parse",
		"github.com/alecthomas/units",
		"github.com/portainer/portainer",
		"go/ast",
		"go/doc",
		"go/scanner",
		"go/token",
		"gopkg.in/alecthomas/kingpin.v2",
		"internal/cpu",
		"internal/nettrace",
		"internal/poll",
		"internal/race",
		"internal/singleflight",
		"io",
		"io/ioutil",
		"math",
		"math/rand",
		"net",
		"net/url",
		"os",
		"path",
		"path/filepath",
		"reflect",
		"regexp",
		"regexp/syntax",
		"runtime",
		"runtime/cgo",
		"runtime/internal/atomic",
		"runtime/internal/sys",
		"sort",
		"strconv",
		"strings",
		"sync",
		"sync/atomic",
		"syscall",
		"text/template",
		"text/template/parse",
		"time",
		"unicode",
		"unicode/utf8",
		"unsafe",
		"vendor/golang_org/x/net/route"
	]
}

猜你喜欢

转载自blog.csdn.net/qq_30062125/article/details/82867828