Go语言的工作空间:通常添加到GOPATH中。

src

bin

pkg

对于bin和pkg两个目录,主要影响go install/get命令,它们会将编译结果安装到这两个目录下,以实现增量编译。

环境变量用于实现GOPATH只是工具链和标准库的存放位置。

在使用Git等版本控制工具的时候,建议忽略pkg和bin目录。直接在src目录或者直接在子包目录下创建仓库。

导入包:必须用import命令,参数是工作空间以src为起始的绝对路径。

除了使用默认的包名以外还可以使用别名机制来实现避免同名冲突问题。

import导入的是路径而不是包名,import的导入方式:

1.import "github.com/test/tester"     默认的方式导入

2.import X "github.com/test/tester"   别名方式导入

3.import . "github.com/test/tester"   简单方式导入(不建议使用,因为有可能会造成命名冲突)

4.import _ "github.com/test/tester"   初始化的方式导入

简便方式常用于代码测试中。未使用的包导入后会报错,可以使用初始化方式进行忽略。

部分工具支持相对路径。

自定义路径:在Web服务器上对应路径名称使用go-import跳转信息即可。

组织结构:

包名通常使用单数形式,源码文件必须必使用UTF-8格式,否则会导致编译出错。使用go list命令可以列出包路径。

main包:可执行的入口(入口函数:main.main)

all包:标准库以及GOPATH中找到的所有包

std/cmd包:标准库以及工具链

documentation库:存储文档信息,无法导入(和目录名无关)

权限:所有成员在包内都能访问,无论是否在同一的源码内,但是只有名称首字母大写才会在包外可视。

初始化:

包内每个源码文件可以定义一个或者是多个初始化函数,但是编译器不保证执行次序。

实际上,所有这些初始化函数(包括标准库和导入的第三方包)都是由编译器自动生成的一个包装函数进行调用,因此可保证在单一线程上执行,且仅仅执行一次。执行次序和依赖关系、文件名以及定义次序有关。

初始化函数之间不应有逻辑关联,最好仅仅处理当前文件的初始化操作。编译器首先确保完成所有全局变量初始化,然后才开始执行初始化函数。如果在初始化函数中引用了全局变量,那么这个变量最好是在定义的是时候直接赋值。

因为无法保证执行的次序搜一遍任何初始化函数中的赋值都有可能延迟无效。

在进行代码重构的时候,我们会将代码陆续的分离出来,以独立包的形式进行维护,此时,基于首字母大小写的访问权限控制是过于粗略的,因为我们希望这些包导出成员仅仅在特定范围内访问,而不是向所有用户公开的。

所保存在internal目录下面的包(包括自身)仅仅能被父目录下面的包(含所有层次的子目录)访问。

依赖管理:引入vendor的机制,专门存放第三方包,实现将源码包和依赖完整打包分发。如果说internal针对内部,那么vendor针对的是外部。vendor比标准库的优先级要高。

从源文件所在目录开始,逐级向上构造vendor全路径,直到发现路径匹配为止。匹配失败,则依旧搜索GOPATH。要使用vendor机制,必须开启"GO15VENDOREXPERIMENT=1"的环境变量,Go1.6中默认是开启的,并且必须设置Go的工作空间。

使用go get下载第三方包时,依旧使用GOPATH第一个工作空间,而不是vendor目录,当前工具链中并没有真正意义上的包依赖管理,好在有第三方工具的实现。