基本规则
- 所有的go文件都是必须组织成包的形式,放在相应文件夹下:
- 建议包名和文件夹名字相同;虽然也可以不同,但会引发使用误解。
- 对于主程序包,也需要放在文件夹下面,注意:
- 不建议使用main作为文件夹名,虽然这个包名是main。
- 也不建议使用src作为文件名,尽管这是允许的,但是会引发误解。
- 建议使用项目名字作为包名。
- go build命令如果不带参数,就是build当前包,当前目录所在的包,即当前目录下面的所有go文件。
import “fmt”
func main() { fmt.Printf(“main::main\n”); foo() }
$ cat foo.go package main
import “fmt”
func foo() { fmt.Printf(“main::foo\n”); }
$ ls -1 foo.go main.go myproject
1. 直接进入项目目录运行 go build,即编译当前包。
1. 不需要设置GOPATH值,缺省就是~/go,因为这是一个自包含项目,不需要引用GOPATH的任何值。
1. 编译生成的可执行文件名就是项目文件夹名。
1. 注意当前目录必须是项目文件所在目录,因为go build没有指定目标包,缺省编译当前目录包;如果不是就不行,那得必须按照golang的项目组织规范来组织。
然后设置GOPATH=path/to/<goproject>,再运行go build myproject,这样就可以在任何目录下面编译,编译生成的可执行文件就在编译所在的目录下,而不是包源文件所在的目录。
<a name="N8LfV"></a>
# 例子2:引用了其他的包
基本规则:
- `import <package>`总是从$GOPATH/src目录下面搜索包,如果找不到就报错。
- 并不会从当前目录下面去搜索,也不会从源文件相对目录下面去搜索。
- GOPATH可以包含多个路径,**中间用冒号(:)隔开**,就像PATH一样。
鉴于此,建议golang项目必须严格按照规范的目录结构组织,哪怕是前面这种自包含的项目。
<a name="cdnv4"></a>
# 例子3:vendor目录的使用
基本规则:
- 使用vendor,项目必须严格按照规范的目录结构组织。
- 即使像例子1中自包含的项目也不能使用vendor
- vender需要在原文件下面创建vendor目录,然后把vendor的文件包放入vendor目录即可,在引用的时候不需要指定vendor路径。
<a name="m7WLY"></a>
# 例子4:vendor和GOPATH谁优先使用
如果一个包在vendor和GOPATH下面都存在那么谁会优先使用呢。<br />结论是:
1. 优先使用vendor目录下面的包。
1. 如果vendor下面没有搜索到,再搜索GOPATH下面的包。
1. 要么完整使用vendor下面的包,要么完整使用GOPATH下面的包,不会混合使用:
1. 假如一个函数定义再GOPATH下面的包里,而没有定义在vendor路径下的同名包里,那么调用者就会报函数未定义错误,因为调用者如果找到有vendor路径下面的包,就不会去找GOPATH下面的包了。
<a name="wQPfg"></a>
# 例子5:vendor的层次搜索
前面提到GOPATH和PATH类似,可以包含多个路径,中间用分号隔开,go在搜索包的时候会按手续从前往后搜搜。那么vendor怎么处理层级关系呢。<br />规则是:
- 从引用文件所在的vendor路径下面搜索。
- 如果没有找到,那么从上层目录的vendor路径下面搜索。
- 直到src的vendor路径下面搜索。
<a name="r4nEB"></a>
# 总结
1. 建议golang项目严格按照golang项目组织方式,即使只是一个自包含的项目。
```bash
<goproject>
|-- src
|-- mainpackage
|-- XXX.go
|-- YYY.go
|-- vendor
|-- deppackage1
|-- XXX1.go
|-- YYY1.go
|-- vendor
|-- deppackage2
|-- XXX2.go
|-- YYY2.go
|-- vendor
|-- VVV1.go
|-- VVV2.go
|-- vendor
- GOPATH使用分号(:)隔开的多个路径。
go编译的时候会从GOPATH/src目录下面搜索import的包。 vender目录放在源文件目录同级,下面包含各个包。