Go 工作空间 深度解析
介绍
这篇文档举例证明了一个简单地 Go package 并且介绍了 go tool
,标准的方法来 fetch, build,and install Go package and commands.
如果要使用 go tool,那么就必须将代码组织成一种特殊的形式。 请仔细的阅读这篇文档,它会教你采用最简单的方法来安装运行你的Go程序。
Workspace 工作空间
Golang 工作空间 :编译工具对源码目录有严格要求,每个工作空间 (workspace) 必须由 bin、pkg、src 三个目录组成。
Go tool 被设计成用来开源公共仓库中的代码,尽管或许你不需要发布你的代码, 但是环境的设置还是一样的。
Go的源代码必须存放在 workspace中。 workspace 是一个目录(directory hierachy),在这个目录下有三个子目录
src
包含 Go 源代码文件, 源代码文件组织成 packages (one package per directory)pkg
包含 package objects (二进制的包)bin
包含 可执行的命令 command(可执行的二进制文件)
go tool 编译(build) 源代码文件(source packages),并且将 resulting binaries 安装在 pkg
和 bin
目录下面。
src 目录下面包含多个 版本控制的仓库, (比如 Git 或者 Mercurial) 用来 跟踪一个或者多个 source package的开发进度。
下面给你一个真实环境中的 workspace 是什么样子的:
bin/
hello # 可执行的命令
outyet # 可执行的命令
pkg/
linux_amd64/
github/golang/example/
stringutil.a # pakcage objects
src/
github.com/golang/example/
.git/ # git repository metadata
hello/
hello.go # command source
outyet/
main.go # command source
main_test.go # test source
stringuitl/
reverse.go # package source
reverse_test.go # test source
这个工作空间 包含一个 代码仓库repository( example仓库),example 仓库由两个命令 command (hello, outyet)和一个库library组成(stringutil)
一个典型的 workspace 会包含多个 source repositories,包含很多 pakcages 和 commands。
大部分的 Go programmers 会 keep all their Go source code and dependencies in a single workspace. (将所有的Go源代码和依赖保存在一个工作空间中)。
另外 从上述例子中也可以看到, bin/ 中命令的名字,pkg/中库的名字 都是文件夹的文字。 src/中包的名字和你 import 时候的名字不一定一样,这一点要区别。
GOPATH 环境变量
GOPATH
环境变量 指明了 你的工作空间的位置。 它很可能是你在编写Go代码的时候需要唯一设置的环境变量。
开始编程:
1. 创建一个工作空间目录。
2. 设置 GOPATH 环境变量。
GOPATH目录可以是任意的,唯一的要求是不能是你安装Go时的目录(/usr/local/go)。
$ mkdir $HOME/go
$ export GOPATH=$HOME/go
为了方便,将工作空间的 bin 子目录 加入到 你的 PATH
环境变量中。
$ export PATH=$PATH:$GOPATH/bin
第一个 program
为了编译和运行一个简单地程序,首先选择一个 package path(这里使用 github.com/usr),创建一个 package directory (包目录)
$ mkdir $GOPATH/src/github.com/usr/hello
第二:在包目录下创建一个文件 名为 hello.go
,包含如下的代码
package main import "fmt" func main() {
fmt.Println("Hello, World.\n")
}
第三: 使用 go tool 来 build and install 这个程序
$ go install github.com/user/hello
注意: 你可以你的计算机的任何文件夹下面运行这个命令。 go tool
会在 $GOPATH
指定工作空间下面搜索 github.com/usr/hello
这个包,并且编译安装这个包。
当然, 如果你在 package directory 下面运行 go install
你就可以忽略 package path。
$ cd $GOPATH/github.com/usr/hello
$ go install
这个命令会 build the hello
command, 产生一个可执行的二进制文件。然后将这个可执行的二进制文件安装到工作目录的 bin
目录下面,文件名称为 hello
(在Windows下面为 hello.ext
,可以看到可执行二进制文件名称和目录的名称保持一致)。 在我们的例子中是: $GOPATH/bin/hello
,也就是 $HOME/go/bin/hello
当有错误发生的时候,go tool
只会 print output,而不会产生二进制文件。 如果这些命令没有产生 output(输出),就表示他们运行成功了。
现在你可以 通过输入 hello
命令的全名 来运行这个命令了
$ $GOPATH/bin/hello
hello, world
或者如果你已经将 $GOPATH/bin
加入到 PATH
中:
$ hello
hello, world
如果你使用源代码版本控制系统,现在这是一个好的时机来 initialize a repository, add the files,and commit you first chagne. Again, this step is optional: you do not need to use source control to write Go code.
$ cd $GOPATH/src/github.com/usr/hello
$ git init
Initialized empty Git repository in /home/user/go/src/github.com/user/hello/.git/
$ git add hello.go
$ git commit -m "initial commit"
[master (root-commit) 0b4507d] initial commit
file chagned, insertion(+)
create mode hello.go
将代码 Push 到远程的仓库留作读者作为一个联系吧。
第一个 Library
现在我们写一个 Library,并且在 hello 程序中使用这个库。
- 首先, 选择一个 package path (我们使用
github.com/user/stringutil
),创建这个 package directory
$ mkdir $GOPATH/src/github.com/usr/stringutil
- 在这个目录中创建一个文件
reverse.go
// Package stringutil contains utility functions for working with strings. //Reverse returns its argument string reversed run-wise left to right.
func Reverse(s string) string {
r := []rune(s)
for i , j := , len(r)-; i < len(r)/; i,j = i+, j- {
r[i], r[j] = r[j], r[i]
}
return string(r)
}
- 测试 这个 pckage compiles with 命令
go build
:
$ go build github.com/user/stringutil
或者你在 这个目录下面,只需要
$ go build
即可。
go build
不会产生任何的文件。 我们需要使用go install
可以 将 package object 放置在 workspace下的 pkg目录下。
$ go install
- 为了确认
stringutil
已经建立(build),我们需要修改hello.go
文件。
package main
import (
"fmt"
"github.com/usr/stringutil"
) func main() {
fmt.Printf(stirngutil.Reverse("!oG, olleH"))
}
- 当 go tool 安装一个 package 或者 一个 binary(可执行二进制),它也会 installs whatever dependencies it has (安装它所依赖的文件). 所以当你 intall
hello
程序的时候
$ go install github.com/user/hell
stringutil
也会自动安装。
运行新版本的程序,你会看见如下结果:
$ hello
Hello, Go!
经过了上述的步骤,你的工作空间现在应该是下面的情况:
bin/
hello # command executalbe 可执行命令
pkg/
linux_amd64/ # this will reflect you OS and architecture
github.com/usre/
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
的目录下, 这个目录 mirrors its source directory. 这是因为 以后 go tool 会找到 package object,并且会避免重新编译。 linux_amd64
是为了平台交叉编译,将会反映你的操作系统和计算机的体系结构。
Go command exectualbes are statically linked。(go command 执行是静态链接的) The package objects need not be present to run Go program.(pakcage object 在Go程序执行的时候是不需要的)。
Package names
在Go源文件中, 第一行语句一定是
package name
其中, name
is the package’s default name for imports. (All files in a package must use the same name
)
Go的惯例是, package name 是 import path 的最后一个元素: 比如,导入的包是 "crypto/rot13"
那么,它的 package name 就应该是 rot13
。 (其实,导入的包名 和 实际的 package name 并不必须要一致。 因为导入的 package 是这个包所在的目录,而这个包所在的目录并不一定和 package name是一致的。但是惯例二者是一样的)
可执行的命令 必须 使用 package main
包名 没有必要在 所有的包中(linked to a single binary)是唯一的,之哟啊 import path(它们的 full file name)是唯一的就可以了。
Testing
Go 有一个轻量级的测试框架: Tesing。 Testing 由 go test
命令 和 testing
包组成。
Testing 可以用作单元测试,也可以用来进行压力测试。
如何使用 Testing 写单元测试:
1. 创建一个文件, 这个文件以 _test.go
结束,比如: reverse_test.go
2. 这个文件包含测试函数: TestXXX ,其中XXX的起始字符不可是小写字母[a-z],测试函数签名为: func (t *testing.T)。
Testing 测试框架会 运行每个测试函数,一旦这个测试函数 调用了 failure function, 比如: t.Error
或者 t.Fail
,那么这个测试就表明失败了。
举例:
1. 向 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, Go", "oG, olleH"}
{"", ""}
} for _, c := range case {
got := Reverse(c, in)
if got != c.want {
t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want)
}
}
}
- 运行测试用例
$ go test github.com/user/stringutil
ok github.com/user/stringutil .165s
As always,如果你在 package directory下面运行 go tool
,你就可以忽略 package path。
$ go test
ok github.com/user/stringutil .165s
如果你有疑问可以,运行go help test 并且看一下 testing package documentation 了解详情。
Remote packages (远程包安装)
go tool
可以用来自动的 fetch packages from remote repositories。(比如 Git 或者 Mercurial)。
举例, 在 Github github.com/golang/example
上有我们上文写过的代码。 如果你在 package’s import path中 包含这个 repository URL,那么 go get
命令将会 自动的 fetch build and install
这个包。(自动的获取,build,安装这个包)
$ go get github.com/golang/example/hello
$ $GOPATH/bin/hello
Hello, Go examples!
如果这个指定的 package 没有在 workspace中,那么 go get
命令将会 把 它放在 $GOPATH
指定的第一个 workspace中。(如果这个 package 已经存在了,那么 go get
将会忽略远程的 fetch,并且执行和 go install
一样的操作)
在 issuing go get
命令之后,现在的工作空间应该是这个样子:
bin/
hello # 可执行的命令
pkg/
linux_amd64/
github/golang/example/
stringutil.a # pakcage objects
github/user/
stringutil.a # package objects
src/
github.com/golang/example/
.git/ # git repository metadata
hello/
hello.go # command source
outyet/
main.go # command source
main_test.go # test source
stringuitl/
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 文件中的 imports 需要使用同样的 import path convention(惯例),这样 go get
命令可以 定位并且安装依赖的 package.
import "github.com/golang/example/stringutil"
这个惯例很重要,大家一定要遵守。并且这个惯例 可以让你的包很轻松地被别人使用。
Go Wiki和godoc.org提供了一些列的 external Go progects.
本文来自:CSDN博客 感谢作者:xiaorenwuzyh 查看原文:Go 工作空间 深度解析
Go 工作空间 深度解析的更多相关文章
- [WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析
[WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析 标签: webkit内核JavaScriptCore 2015-03-26 23:26 2285 ...
- 第37课 深度解析QMap与QHash
1. QMap深度解析 (1)QMap是一个以升序键顺序存储键值对的数据结构 ①QMap原型为 class QMap<K, T>模板 ②QMap中的键值对根据Key进行了排序 ③QMap中 ...
- Deep Learning模型之:CNN卷积神经网络(一)深度解析CNN
http://m.blog.csdn.net/blog/wu010555688/24487301 本文整理了网上几位大牛的博客,详细地讲解了CNN的基础结构与核心思想,欢迎交流. [1]Deep le ...
- (转载)(收藏)OceanBase深度解析
一.OceanBase不需要高可靠服务器和高端存储 OceanBase是关系型数据库,包含内核+OceanBase云平台(OCP).与传统关系型数据库相比,最大的不同点, 是OceanBase是分布式 ...
- Kafka深度解析
本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/01/02/Kafka深度解析 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅 ...
- java内存分配和String类型的深度解析
[尊重原创文章出自:http://my.oschina.net/xiaohui249/blog/170013] 摘要 从整体上介绍java内存的概念.构成以及分配机制,在此基础上深度解析java中的S ...
- Unity加载模块深度解析(Shader)
作者:张鑫链接:https://zhuanlan.zhihu.com/p/21949663来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 接上一篇 加载模块深度解析(二 ...
- Unity加载模块深度解析(网格篇)
在上一篇 加载模块深度解析(一)中,我们重点讨论了纹理资源的加载性能.这次,我们再来为你揭开其他主流资源的加载效率. 这是侑虎科技第53篇原创文章,欢迎转发分享,未经作者授权请勿转载.同时如果您有任何 ...
- 深度解析Java8 – AbstractQueuedSynchronizer的实现分析(上)
本文首发在infoQ :www.infoq.com/cn/articles/jdk1.8-abstractqueuedsynchronizer 前言: Java中的FutureTask作为可异步执行任 ...
随机推荐
- 青岛和深圳,两座条件相似的城市,为何GDP相差这么大
深圳和青岛,是一对非常有意思的城市.两者都是沿海城市:两者都是所在省的经济强市:两者都是副省级城市,但都不是省会:两者GDP都超过所在省的省会城市.当然,两个城市也有相当大的差距,一个位于南方,一个位 ...
- C#Application:Exit与ExitThread 解释
Application.Exit(); 方法停止在所有线程上运行的所有消息循环,并关闭应用程序的所有窗口 Application.ExitThread 方法 退出当前线程上的消息循环,并关闭该线程上的 ...
- linux简单命令---网络编程
---------------------------------------------------------------------------------------------------- ...
- python 连接 hive
1.python连接hive,其实是连接hiveserver,连接的包的impyla impyla安装: error: cc1plus 没有文件或目录 需要安装gcc 和g++,并且版本保持一致 er ...
- eclipse中Maven web项目的目录结构浅析
刚开始接触maven web项目的时候,相信很多人都会被它的目录结构迷惑. 为了避免初学者遇到像我一样的困扰,我就从一个纯初学者的视角,来分析一下这个东西. 1,比如说,我们拿一个常见的目录结构来看, ...
- 测试ssh转发
端口转发提供: 1.加密 SSH Client 端至 SSH Server 端之间的通讯数据. 2.突破防火墙的限制完成一些之前无法建立的 TCP 连接. 但是只能转发tcp连接,想要转发UDP,需要 ...
- .Net Core 2.*+ InfluxDB+Grafana+App Metrics实时性能监控
前言 .net core 2.* 实施性能监控 这个工具其实给运维 大大们用起来是更爽的.但是Grafana现在还没有找到中文版. 本文需要了解的相关技术与内容: InfluxDb(分布式时序数据库, ...
- 感知器做二分类的原理及python实现
本文目录: 1. 感知器 2. 感知器的训练法则 3. 梯度下降和delta法则 4. python实现 1. 感知器[1] 人工神经网络以感知器(perceptron)为基础.感知器以一个实数值向量 ...
- 【Gym - 100923I】Por Costel and the Pairs(思维题)
Por Costel and the Pairs Descriptions 有T组测试样例 有n个男的,n个女的,第i个人都有为当前一个大小为i的懒惰值,当一男一女懒惰值的乘积<=n他们就就可以 ...
- 云计算openstack核心组件--glance-镜像服务(6)
glance做什么 OpenStack 由 Glance 提供 Image 服务 获取镜像位置 https://docs.openstack.org/image-guide/obtain-images ...