Golang编程语言是一个开源项目,它是一种表现力强、简洁、高效的语言。它的并发机制使得编写程序更容易从多核和网络化机器中获得最大收益,新类型系统实现了灵活的模块化程序构建。可以快速编译成机器代码,也具有便利的垃圾回收机制和运行时发射功能,作为一种快速、静态类型的编译语言,让人感觉像一种动态类型的解释语言。在深入Golang之前,首先要了解它的工作环境
Golang环境搭建
Golang发行版系统支持
官方二进制发行版可用于FreeBSD(Release 10-STABLE及更高版本)、Linux、MacOS(10.10及更高版本)、Windows操作系统以及32位(386)和64位(AMD64)x86处理器体系结构。go二进制发行版可用于这些受支持的操作系统和体系结构。在继续之前,请确保您的系统满足这些要求
如果二进制发行版不适用于目标操作系统和体系结构的组合,请尝试从源安装或安装gccgo
以Go1.13.1为例进行安装介绍
安装包链接
// MicroSoft Windows(Windows7及更高版本)
https://dl.google.com/go/go1.13.1.windows-amd64.msi
// Apple MacOS (MacOS 10.11及更高版本)
https://dl.google.com/go/go1.13.1.darwin-amd64.pkg
// Linux (Linux 2.6.23及更高版本)
https://dl.google.com/go/go1.13.1.linux-amd64.tar.gz
// 源码
https://dl.google.com/go/go1.13.1.src.tar.gz
安装Go工具
// 对Linux、MacOS及FreeBSD系统,下载适当的tar文件,抽取文件到 /usr/local 目录,创建Go目录树 /usr/local/go(需要root权限)
tar -C /usr/local -xzf go$VERSION.$OS-$ARCH.tar.gz
// 设置环境变量
mkdir -p $HOME/workspace
vim $HOME/.bashrc
export GOPATH=$HOME/workspace
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin
source $HOME/.bashrc
// WindowsOS 除了从源码安装之外,Go为Windows用户提供了两个安装选项:一个是zip归档文件,这需要配置一些环境变量;另一个是msi安装
// 通过zip文件解压到C盘,设置环境变量GOROOT及PATH
安装验证 通过简单程序验证Go是否正确安装,如下所示
// 新建project目录
mkdir -p $HOME/workspace/src/hello
cd $HOME/workspace/src/hello
// 编辑简单程序 hello.go
vim hello.go
package main
import "fmt"
func main() {
fmt.Printf("hello, world\n")
}
// 编译测试程序: 命令执行后将生成一个名为 hello的可执行文件
go build
// 执行 hello,显示`hello, world`,说明安装成功
./hello
`hello, world`
// 安装到 workspace/bin
go install
// 从 workspace/bin 中移除 hello 命令
go clean -i
安装额外的Golang版本 在同一台机器上安装多个Go版本可能很有用,例如测试包需要通过多个Go版本。安装好一个版本后就可以安装另一个版本(例如 1.10.7),如下所示
go get golang.org/dl/go1.10.7
go1.10.7 download
// 新下载的版本使用方式
go1.10.7 version
`go version go1.10.7 linux/amd64`
卸载 从系统中删除现有go安装,只需删除go目录和环境变量即可
插件和IDE编辑器
Go社区提供了丰富的IDE支持来增强您的日常编辑、导航、测试和调试体验,例如
- vim: vim-go 插件提供Go编程语言支持
- Visual Studio Code: 为Go编程语言提供Go扩展支持
- GoLand: GoLand 作为一个独立的IDE或IntelliJ IDEA Ultimate的插件发行
- Atom: 来自GitHub的基于JavaScript的编辑器,它提供了 Go-Plus 支持
- ...
如何编写Go代码
接下来以一个简单的示例介绍Go工具及获取、构建和安装Go包和命令的标准方法
代码组织
Go程序员通常将所有Go代码保存在一个workspace中
workspace可以包含许多版本控制库(例如git)
每个repo包含一个或多个包
每个包由单个目录中的一个或多个Go源文件组成
-
包目录的路径决定了它的导入路径
与其他编程环境不同,在这些环境中,每个项目都有一个单独的workspace,并且workspace与版本控制库密切相关
workspaces 工作空间是一个目录层次结构,其根目录有两个目录
src 包含Go源文件。src子目录通常包含多个版本控制库(如git或mercurial),用于跟踪一个或多个源码包的开发
-
bin 包含可执行命令。go工具构建二进制文件并将其安装到bin目录
以下示例展示workspace目录树的层级结构
bin/
hello # 可执行命令
outyet # 可执行命令
src/
github.com/golang/example/
.git/ # Git仓库元数据
hello/
hello.go # 命令源码
outyet/
main.go # 命令源码
main_test.go # 测试源代码
stringutil/
reverse.go # 包源代码
reverse_test.go # 测试包源代码
golang.org/x/image/
.git/ # Git仓库元数据
bmp/
reader.go # 包源代码
writer.go # 包源代码
... (更多repo及包在此处省略) ...
以上目录树展示了一个workspace包含两个repo: example和image。example库包含两个命令hello和outyet和一个库stringutil; image库包含bmp包和其他。一个典型的workspace包含许多包和命令的源码存储库,大多数Go程序员将所有Go源代码和依赖项保存在一个工作区中
Tips 不应使用符号链接将文件或目录链接到workspace中
GOPATH环境变量 gopath指定workspace的位置,默认为$HOME/go
目录,如果你希望workspace指向其他位置,则需要将GOPATH设置为该目录的路径
tips GOPATH不能与go安装路径相同
export GOPATH=$HOME/SOMEDIR
命令打印有效的当前gopath;如果环境变量未设置,则打印默认位置
为了方便,将workspace的bin子目录添加到PATH中
export GOPATH=$(go env GOPATH)
export PATH=$PATH:$(go env GOPATH)/bin
Import paths 导入路径是唯一标识包的字符串。包的导入路径对应于其在workspace内或远程repo中的位置。标准库中的包被赋予短的导入路径,例如"fmt"和"net/http"; 对于您自己的包,您必须选择一个基本路径,该路径不太可能与将来添加到标准库或其他外部库的内容冲突
如果将代码保存在某个源码仓库中,则应使用该库的根作为基本路径。例如,如果您在github.com/user上有一个github帐户,那应该是您的基本路径
第一个程序 使用 github.com/user
作为基本路径,在workspace内创建一个目录,用于保存源代码
mkdir -p $GOPATH/src/github.com/user
## 要编译和运行一个简单的程序,首先选择一个包路径(github.com/user/hello)并在workspace内创建一个相应的包目录
mkdir $GOPATH/src/github.com/user/hello
## 接下来在这个目录下创建一个文件名为hello.go,其中包含以下go代码
package main
import "fmt"
func main() {
fmt.Println("Hello, world.")
}
## 使用go工具构建和安装该程序
go install github.com/user/hello
## 现在您可以从系统上的任何位置运行此命令
## go工具通过在gopath指定的工作区内查找github.com/user/hello包来查找源代码
## 如果从包目录运行 go install,也可以省略包路径
cd $GOPATH/src/github.com/user/hello
## 这个命令编译hello.go生成可执行文件hello,然后安装hello(Windows中hello.exe)到workspace bin目录下($GOPATH/bin/hello)
go install
## 当错误发生时,go工具将会打印输出,如果命令没有产生输出,说明它已经执行成功
## 现在可以执行以下命令 $GOPATH/bin/hello 或 hello将产生以下输出
Hello, world.
## 如果您使用的是源代码管理系统,现在是初始化repo、添加文件和提交更改d的好时机;当然,这个步骤是可选的
cd $GOPATH/src/github.com/user/hello
git init
git add hello.go
git commit -m "initial commit"
git push -u origin
第一个库 编写一个库并从hello程序中使用它
## 同样,第一步是选择包路径(github.com/user/stringutil)并创建包目录
mkdir $GOPATH/src/github.com/user/stringutil
## 接下来,在该目录中创建一个名为reverse.go的文件,其中包含以下内容
// Package stringutil contains utility functions for working with strings.
package stringutil
// Reverse returns its argument string reversed rune-wise left to right.
func Reverse(s string) string {
r := []rune(s)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r)
}
## 使用 go build 测试包: 这不会产生输出文件。相反,它将编译后的包保存在本地生成缓存中
go build github.com/user/stringutil
## 确认stringutil包生成后,修改原来的hello.go(路径为 $GOPATH/src/github.com/user/hello)
package main
import (
"fmt"
"github.com/user/stringutil"
)
func main() {
fmt.Println(stringutil.Reverse("!oG ,olleH"))
}
## install hello
go install github.com/user/hello
## 运行新版本的hello,将会看到输出反向字符串
hello
> Hello, Go!
# 完成这个步骤后,您的workspace目录树结构为
bin/
hello # command executable
src/
github.com/user/
hello/
hello.go # command source
stringutil/
reverse.go # package source
包名
## Go源文件中的第一个语句必须是,其中name是包导入的默认名称(包中的所有文件必须使用相同的包名)
package name
## go的约定是包名是导入路径的最后一个元素:作为“crypto/rot13”导入的包应命名为rot13
## 可执行命令必须始终使用 package main,没有要求包名称在链接到单个二进制文件的所有包中都是唯一的,只要求导入路径(它们的完整文件名)是唯一的
测试 Go有一个轻量级的测试框架,由go test命令和testing包组成。通过创建一个以_test.go结尾的文件来编写测试,该文件包含名为TestXXX的函数它的签名为func (t *testing.T)
,测试框架运行每一个这样的测试函数;如果测试函数调用一个失败函数,如t.Error或t.Fail,则认为测试失败
为stringutil包添加一个测试,创建一个文件$GOPATH/src/github.com/user/stringutil/reverse_test.go
包含下面的代码
package stringutil
import "testing"
func TestReverse(t *testing.T) {
cases := []struct {
in, want string
}{
{"Hello, world", "dlrow ,olleH"},
{"Hello, 世界", "界世 ,olleH"},
{"", ""},
}
for _, c := range cases {
got := Reverse(c.in)
if got != c.want {
t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want)
}
}
}
接下来使用go test
命令运行测试
go test github.com/user/stringutil
> ok github.com/user/stringutil 0.165s
Remote packages 导入路径可以描述如何使用修订控制系统(如git或mercurial)获取包源代码,Go工具使用此属性自动从远程存储库获取包。例如,本文中描述的示例也保存在github github.com/golang/example上的git仓库中。如果在包的导入路径中包含repo URL,则go get将自动获取、构建和安装它
go get github.com/golang/example/hello
$GOPATH/bin/hello
如果指定的包不在工作区中,go get会将其放在GOPATH指定的第一个workspace中(如果包已经存在,则go get跳过远程获取,其行为与go install相同)。在执行上面的go get命令之后,workspace目录树现在应该如下所示
bin/
hello # command executable
src/
github.com/golang/example/
.git/ # Git repository metadata
hello/
hello.go # command source
stringutil/
reverse.go # package source
reverse_test.go # test source
github.com/user/
hello/
hello.go # command source
stringutil/
reverse.go # package source
reverse_test.go # test source
托管在github上的hello命令依赖于同一repo中的stringutil包。hello.go文件中的导入使用相同的导入路径约定,因此go get命令也可以定位和安装依赖包
import "github.com/golang/example/stringutil"
小结
作为Golang系列文章的开篇,本文首先介绍Golang开发环境搭建,结合示例简单介绍go工具的使用方法