Go实战(一) 环境搭建
Table of Contents
1 注
2 Ubuntu 16.04 + Go
2.1 配置环境变量
/etc/profile
是针对所有用户, 登录时读取, 重启才能生效.
~/.profile
针对当前用户, 登录时读取, 使用 source
命令即可生效.
~/.bashrc
针对当前用户, 打开 bash shell 时读取, 使用 source
命令即可生效.
这边, 我们把环境变量配置到 ~/.profile
中.
打开 ~/.profile
, 在文件末尾添加如下代码:
export GOROOT=/usr/local/go export PATH=$PATH:$GOROOT/bin
使用 source ~/.profile
使配置生效.
GOROOT
表示 Go 的安装目录, 这样我们开发 Go 的 IDE 就可以自动找到我们的 Go 安装目录, 自动配置 Go SDK.
第2句把 /usr/local/go/bin
目录添加到 PATH 中, 这样可以在终端直接使用 go 命令.
2.2 设置工作目录
目录目录是我们用来存放开发时的源码的地方. 我们使用 GOPATH 来保存这个变量, 写入到 ~/.profile
中.
打开 ~/.profile
, 在末尾添加:
export GOPATH=$HOME/go export PATH=$GOPATH/bin:$PATH
使用 source ~/.profile
使配置生效.
在 GOPATH 目录下, 一般有三个子目录, 如果没有, 则自己新建一下. 如下图所示:
其中
- bin: 存放
go install
命令生成的可执行文件, 我们在上面已经将其路径加入到 PATH 环境变量中了, 这样可以直接在终端使用我们Go开发生成的程序. - pkg: 存放 Go 编译生成的文件.
- src: 存放 Go 源代码, 不同工程项目的代码以包名区分.
2.2.1 src目录
这里再对 src 目录进行讨论.
如果我们有多个项目, 就要使用包名来组织我们的目录结构. 一般如果包名使用网站域名开头, 就不会有重复. 如: github.com 开头, 后面再加上自己的用户名. 如下图所示:
如果我们要引用一个包, 可以通过包路径来引入. 包路径就是从 src 目录开始的. 如:
import ( "github.com/hyperledger/fabric/core/chaincode/shim" )
在 shim
目录下, 有许多 .go 文件.
2.2.1.1 test
3 Hello World
新建自己的工程目录: mkdir -p $GOPATH/src/github.com/pinvondev/hello
.
进入自己的工程目录.
新建文件 main.go
, 代码如下:
package main import ( "fmt" ) func main() { fmt.Println("Hello World") }
3.1 运行
在 $GOPATH/src/github.com/pinvondev/hello 目录下, 运行 go run main.go
, 就可以看到打印的 Hello World 了.
package 是关键字, 定义一个包, 和 Java 中的 package 一样, 是模块化的关键.
- main包: 这是一个特殊的包名, 它表示当前是一个可执行程序, 而不是一个库.
- import: 关键字, 表示要引入的包, 只有引入后, 才能被使用.
- fmt包: 引入这个包后, 我们就可以使用它的函数了.
- main(): 主函数, 表示程序执行的入口.
- Println(): fmt 包中的函数, 用于打印输出.
3.2 安装
安装的意思就是生成可执行程序, 我们可以使用 go install
命令, 将程序安装到 $GOPATH/bin 目录下:
go install github.com/pinvondev/hello
安装成功以后, 我们直接在终端执行 hello
命令, 就可以打印出 Hello World 了.
3.3 跨平台编译
查看编译环境: go env
, 结果类似下图:
其中, GOOS
指的是目标操作系统, GOARCH
指的是目标处理器的架构. 这两个变量可指定的值都定义在了 $GOROOT/src/go/build/syslist.go 里面. 如图所示:
这两个变量的值的组合, 可参考文档: $GOROOT/doc/install-source.html 如下图所示:
具体编译的时候, 比如要生成 linux 64 位的程序, 可以这样:
GOOS=linux GOARCH=amd64 go build github.com/pinvondev/hello
这样的好处是, 环境变量的更改只对本次运行有效, 不会更改我们的默认配置.
4 获取远程包
go get
命令可以获取远程包, 参数是完整的包名.
go get -v github.com/derekparker/delve/cmd/dlv
这样, 这个库就可以下载到 $GOPATH/src 目录下了. 后面使用的时候, 可以直接像导入其他包一样来导入.
go get
命令的本质是使用了版本控制工具(如 git)来下载, 所以在使用之前, 必须确保安装了这些版本控制工具.
如果远程包有更新, 可以用 -u 参数来进行更新. 如:
go get -u -v ...
知道原理之后, 由于 google 的东西很多被墙, 如果使用 go get
下载不下来, 也可以使用浏览器下载, 然后放到 $GOPATH/src 目录下, 再进行安装.
5 Go 包管理
Go 语言自带的包, 放在 $GOROOT/src 目录里, 引入的时候省略 $GOROOT/src, 如下所示:
import "net/http"
Go 会到 $GOROOT/src 中寻找 net/http.
如果要引入自定义的包, 有两种方式:
- 相对路径(不建议): import "./model"
- 绝对路径: import "github.com/pinvondev/tools". Go 会到 $GOPATH/src 目录下寻找相应的包.
Go 会优先到 GOROOT 里搜索, 如果没找到, 再到 GOPATH 里搜索, 如果还没找到, 则到托管该代码的远程服务器下载, 但是如果远程服务器也没找到, 就会报错.
5.1 main 包
如果把一个 go 程序的包名声明为 main 时, 就等于告诉 go 编译器, 这是一个可执行程序, 于是 go 编译器就会尝试将其编译成一个二进制的可执行文件.
main 包, 必须包含程序的入口函数 main(). 在 main 包的 go 程序目录下, 执行 go build
, 可以生成一个可执行文件. 跟 go install
生成的文件是一样的, 只是 go build
生成的文件不放在 $GOPATH/bin 目录下.
5.2 包名重复
如果我们导入的包名重复了, 可以对包名进行重命名. 如:
import ( "fmt" myfmt "mylib/fmt" )
5.3 导入一个不使用的包
Go 语言规则, 导入的包必须要使用, 否则会编译错误. 如果非要导入一个不使用的包, 则把包重命名为空白标志符"_", 如下:
import ( _ "mylib/fmt" )
5.4 包的 init()
每个包都可以有任意数量的 init(), 这些 init() 会在 main() 之前执行, 用来初始化变量, 设置包, 或其他需要在程序执行前的引导工作. 如之前的导入一个不使用的包, 就是想执行那个包里的 init().
以数据库的驱动为例, Go 统一了关于数据库的访问, 使用 databases/sql 抽象了一层数据库的操作, 无论我们使用的数据库是 MySQL, 还是 Postgre, 还是别的, 都可以使用同样的程序来访问. 这个原理就是在 init() 里面, 把实现好的驱动注册到 sql 包里, 这样我们就直接使用它来操作数据库了.
首先, 我们创建一个包, 把相应的数据库驱动注册到包里:
package mysql import ( "database/sql" ) func init() { sql.Register("mysql", &MySQLDriver{}) }
然后, 在需要使用数据库操作的地方, 这么写:
import "database/sql" import _ "github.com/pinvondev/mysql" db, err := sql.Open("mysql", "user:password@dbname")
这边, 我们对 mysql 包进行重命名, 只执行里面的 init(). 以后, 我们只需要利用 sql 进行操作, 不用考虑具体的数据库是哪个.
6 go 命令
在终端输入 go, 可以看到 go 命令的解释.
在终端输入 go help command, 可以看到关于该 command 的介绍. 如 go help build
6.1 go build
使用方法:
usage: go build [-o output] [-i] [build flags] [packages]
go build go build hello.go
这两条命令等价, 都是使用当前目录编译.
go build
本质上需要一个路径作为参数, 让编译器可以找到哪些需要编译的 go 文件. packages 就是一个路径. 如:
go build github.com/pinvondev/hello
通配符 ... 表示匹配所有字符串, 所以:
go build github.com/pinvondev/hello/...
该命令表示编译 github.com/pinvondev/hello 目录下的所有包.
6.2 go clean
可以使用一个包(路径)作为参数.
该命令可以清理我们编译时生成的文件:
go clean
6.3 go run
该命令在 go build 之后, 自动执行可执行文件.
6.4 go env
查看 go 环境信息.
6.5 go install
该命令把生成的可执行文件或者库安装到对应的目录下.
6.6 go get
该命令从网上下载或更新指定的包及依赖包, 并对它们进行编译和安装.
-u: 更新
-v: 显示进度及调试信息
6.7 go fmt
该命令可以对源代码进行格式化, 得到和 Go 源代码一样的风格.
6.8 go vet
检查代码中的错误.
6.9 go test
go test
命令对文件有一些要求:
- 文件名要以
_test.go
结尾 - 测试文件中要包含若干测试函数
- 测试函数要以 Test 为前缀, 接收 *testing.T 类型的参数
6.10 go doc
6.10.1 本地浏览API文档
godoc -http=:6060
然后就可以打开浏览器, 输入 localhost:6060 就可以访问了.
6.10.2 生成自己的文档
文档就是注释. Go 的注释与 C++ 相同.
写完注释后, 在终端进入当前目录, 输入 go doc
或 godoc
, 就可以看到注释的文档了.
6.10.3 添加文档示例
- 示例代码必须单独存放在一个文件中.
- 在这个 go 文件中, 定义一个名字为 Example() 的函数, 参数为空.
- 示例的输出采用注释的方式, 以 //Output: 开头, 真正的输出另起一行, 每行输出占一行.
Generated by Emacs 25.x(Org mode 8.x)
Copyright © 2014 - Pinvon - Powered by EGO