Go入门:怎样编写Go代码
2016-07-07 07:22
399 查看
Go入门:怎样编写Go代码
Go入门怎样编写Go代码基本介绍
代码结构
基本原则
工作空间workspace
GOPATH环境变量
包路径
第一个Go程序
第一个库
包命名
测试
远程包
接下来的事情
基本介绍
本文将描述如何开发一个简单的go包,并简单介绍go命令,以及获取、生成、安装go包和命令的标准方法。代码结构
基本原则
将所有Go代码放在一个工作空间(workspace)下。一个工作空间包含多个代码仓库。
每个仓库有一个或多个包(packages)。
每个包又包含一个或多个Go代码源文件。
包的路径在import中体现。
工作空间(workspace)
每个工作空间根目录下包括:- src Go源代码
- src文件夹下放置多个版本控制的仓库(项目)。
- pkg 包对象
- bin 生成的可执行文件
go命令编译源文件,并生产对应的结果文件到pkg和bin目录。
一个典型的go工作空间是这样子的:
上边的例子包括两个仓库、项目(example和image)。其中项目example包括两个命令(hello和outyet)和一个二进制库(stringutil);项目image包含bmp包和其它。
一个典型的go工作空间包括多个代码库(由包和命令组成)。大多数程序员会把所有源代码和依赖放到一个工作空间。
各种不同的代码包编译生成命令和类库。这个我们以后单独讨论。
GOPATH环境变量
GOPATH环境变量又来标明你的工作空间的位置。大多数情况下也是开发Go代码唯一要设置的一个环境变量。开始所有工作之前,你需要创建一个总的目录来当做工作空间,并且设置GOPATH变量指向这个目录。工作空间可以在任何目录下,在接下来的文档中我们使用home目录下的work目录HOME/work来做例子。(一般也会直接把个人home目录HOME设为工作空间)
注意:工作目录不能跟Go的安装目录一样。
$ mkdir $HOME/work $ export GOPATH=$HOME/work
方便起见,也会直接把工作空间下的bin目录添加到PATH路径(这样就可以在任意目录下直接执行生成的Go命令)。
$ export PATH=$PATH:$GOPATH/bin
点击这里获取更多关于GOPAT环境变量的设置帮助。
包路径
包路径用来唯一标记一个包,包路径反映了包在本地工作空间或远程代码库(接下来会详细说明)中的位置。标准库中的包直接使用短包路径,比如“fmp”或“net/http”。但是对于自己编写的包,基础路径的名字不能与标准库和其它一些外部库冲突。
如果你的代码直接保存在一些版本控制的代码库里,应该直接使用代码库的根目录作为基本路径。比如,如果你的代码都存放在github的user用户下(github.com/user),那github.com/user就应该是基本路径。
即使你现在还没有打算把代码发布带远程代码仓库,最好还是按照以后准备提交代码仓库的方式组织代码结构。实际中可以使用任何组合来标记路径名称,只要对应的路径名称不与基本库冲突。
我们接下来将使用githun.com/user作为基本路径。在工作空间下创建对应的目录来保存代码:
$ mkdir -p $GOPATH/src/github.com/user
第一个Go程序
为了编译和运行一个简单的Go程序,需要在工作空间下创建包路径(我们接下来将使用github.com/user/hello)和对应的包目录。$ mkdir $GOPATH/src/github.com/user/hello
接下来,在目录下新建一个hello.go文件,包含以下内容:
package main import "fmt" func main() { fmt.Printf("Hello, world.\n") }
现在可以使用下边的go工具生成和安装这个程序:
$ go install github.com/user/hello
你可以在任何目录下执行上边的命令。go工具会根据GOPATH在对应工作空间下查找github.com/user/hello包。
你也可以忽略包路径而直接在对应代码包文件夹下执行go install命令:
$ cd $GOPATH/src/github.com/user/hello $ go install
以上命令会生成hello命令,同时产生可执行二进制文件。然后将对应的二进制命令安装到工作空间的bin目录下。在我们的这个例子中,会直接安装到GOPATH/bin/hello,也就是HOME/work/bin/hello。
go命令执行成功时不会有任何输出,只有发生错误的时候才会打印对应的错误信息。
现在你可以在命令行中使用完整路径来执行这个程序:
$ $GOPATH/bin/hello Hello, world.
或者,如果已经添加$GOPATH/bin到PATH,可以直接输入二进制名称来执行程序:
$ hello Hello, world.
如果你正要使用版本控制系统,现在可以初始化代码仓库、添加文件,做第一次提交。再次强调,使用版本控制系统不是必须的。
$ cd $GOPATH/src/github.com/user/hello $ git init Initialized empty Git repository in /home/user/work/src/github.com/user/hello/.git/ $ git add hello.go $ git commit -m "initial commit" [master (root-commit) 0b4507d] initial commit 1 file changed, 1 insertion(+) create mode 100644 hello.go
第一个库
接下来我们来写一个库给hello程序使用。跟可执行程序一样,第一步还是创建包路径和对应的包文件夹。
$ 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
或者在包目录下直接执行go build:
$ go build
到这里还不会产生任何文件。你必须执行go insall命令生成输出库文件。
确认库文件已经产生后,就可以在之前的hello.go中使用这个库了:
package main import ( "fmt" "github.com/user/stringutil" ) func main() { fmt.Printf(stringutil.Reverse("!oG ,olleH")) }
无论使用go安装包还是二进制文件,所有相关的依赖都会自动安装。所以当你安装hello程序时:
$ go install github.com/user/hello
对应的stringutil包也会自动被安装。
执行新的hello程序,你可以看到一个新的、已经被反转的消息:
$ hello Hello, Go!
所有这些以后,你的工作空间应该是这样的:
bin/ hello # command executable pkg/ linux_amd64/ # this will reflect your OS and architecture github.com/user/ stringutil.a # package object src/ github.com/user/ hello/ hello.go # command source stringutil/ reverse.go # package source
注意:go install会把库文件stringutil.a放到pkg/linux_amd64下边(目录结构跟源代码结构一样)。这样可以go命令可以直接找到对应的包对象,避免不必要的重复编译。linux_amd64是为了根据操作系统和你的系统架构交叉编译。
所有Go可执行程序都通过静态方式链接在一起,所以在运行时是不需要相关的包对象(库)。
包命名
所有Go源代码都以下边的语句开始:package name
其中name就是包引用是默认的名称。一个包中的所有文件必须使用同一个包名。
可执行命令的包名必须是main。
一个二进制文件下所有的包名不需要唯一,但是引用路径必须唯一。
了解更多关于Go的命名规范,可以参考实效Go编程。
测试
Go自带了一个轻量级的测试框架,由go test命令和testing包组成。你可以通过新建xx_test.go写一个测试,其中包含若干个TestXXX函数。测试框架会自动执行这些函数;如果函数中包含tError或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
同样,在包文件夹下可以忽略包路径而直接执行go test命令:
$ go test ok github.com/user/stringutil 0.165s
远程包
包的引用路径用来描述如何通过版本控制系统获取包的源代码。go工具通过引用路径自动从远程代码仓库获取包文件。比如本文中用的例子也对应的保存在github.com/golang/example下。go可以通过包的代码仓库的url直接获取、生成、安装对应的包。$ go get github.com/golang/example/hello $ $GOPATH/bin/hello Hello, Go examples!
如果工作空间中不存在对应的包,go会将对应的包放到GOPATH环境变量指明的工作空间下。(如果包已经存在,go跳过代码拉去而直接执行go install)。
执行上边的go get命令后,工作空间文件夹下是这样的结果:
bin/ hello # command executable pkg/ linux_amd64/ github.com/golang/example/ stringutil.a # package object github.com/user/ stringutil.a # package object 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命令依赖于同个仓库下的stringutil库。hello.go使用同样的路径进行导入,所以go get命令能够直接找到并安装对应的依赖包。
import "github.com/golang/example/stringutil"
这也是你共享Go包的最好方式。
关于go工具远程包的更多信息,可以参考Go - 导入路径帮助文档。
接下来的事情
你可以订阅golang-announce邮件列表收取Go新版本的发布信息通知。阅读高效Go编程来学习如何编写清晰、优雅的Go代码。
到这里学习Go编程语言。
访问Go文档深入了解Go以及基本库和工具。
到这里就结束了,参考原文How to Write Go Code.
相关文章推荐
- SQLSERVER 中GO的作用详解
- 在Go语言程序中使用gojson来解析JSON格式文件
- 举例详解Go语言中os库的常用函数用法
- Go语言中函数的参数传递与调用的基本方法
- 深入解析Go语言的io.ioutil标准库使用
- GO语言的IO方法实例小结
- Go语言的os包中常用函数初步归纳
- Go语言中数组的基本用法演示
- GO语言类型转换和类型断言实例分析
- 深入解析Go语言编程中的递归使用
- 初步解读Golang中的接口相关编写方法
- Go语言实现的最简单数独解法
- 详解Golang编程中的常量与变量
- Go实现比较时间大小
- 深入剖析Go语言编程中switch语句的使用
- 简单讲解Go程序中使用MySQL的方法
- Go语言的Windows下环境配置以及简单的程序结构讲解
- 在Go程序中实现服务器重启的方法
- Go语言流程控制之goto语句与无限循环
- 在Mac OS上安装Go语言编译器的方法