3.1 包
所有 Go 语言的程序都会组织成若干组文件,每组文件被称为一个 包 。这样每个包的代码都可以作为很小的复用单元,被其他项目引用。让我们看看标准库中的 http
包是怎么利用包的特性组织功能的:
net/http/
cgi/
cookiejar/
testdata/
fcgi/
httptest/
httputil/
pprof/
testdata/
这些目录包括一系列以.go 为扩展名的相关文件。这些目录将实现 HTTP 服务器、客户端、测试工具和性能调试工具的相关代码拆分成功能清晰的、小的代码单元。以 cookiejar
包为例,这个包里包含与存储和获取网页会话上的 cookie 相关的代码。每个包都可以单独导入和使用,以便开发者可以根据自己的需要导入特定功能。例如,如果要实现 HTTP 客户端,只需要导入 http
包就可以。
所有的.go 文件,除了空行和注释,都应该在第一行声明自己所属的包。每个包都在一个单独的目录里。不能把多个包放到同一个目录中,也不能把同一个包的文件分拆到多个不同目录中。这意味着,同一个目录下的所有.go 文件必须声明同一个包名。
3.1.1 包名惯例
给包命名的惯例是使用包所在目录的名字。这让用户在导入包的时候,就能清晰地知道包名。我们继续以 net/http
包为例,在 http
目录下的所有文件都属于 http
包。给包及其目录命名时,应该使用简洁、清晰且全小写的名字,这有利于开发时频繁输入包名。例如, net/http
包下面的包,如 cgi
、 httputil
和 pprof
,名字都很简洁。
记住,并不需要所有包的名字都与别的包不同,因为导入包时是使用全路径的,所以可以区分同名的不同包。一般情况下,包被导入后会使用你的包名作为默认的名字,不过这个导入后的名字可以修改。这个特性在需要导入不同目录的同名包时很有用。3.2 节会展示如何修改导入的包名。
3.1.2 main
包
在 Go 语言里,命名为 main
的包具有特殊的含义。Go 语言的编译程序会试图把这种名字的包编译为二进制可执行文件。所有用 Go 语言编译的可执行程序都必须有一个名叫 main
的包。
当编译器发现某个包的名字为 main
时,它一定也会发现名为 main()
的函数,否则不会创建可执行文件。 main()
函数是程序的入口,所以,如果没有这个函数,程序就没有办法开始执行。程序编译时,会使用声明 main
包的代码所在的目录的目录名作为二进制可执行文件的文件名。
命令和包 Go 文档里经常使用命令(command)这个词来指代可执行程序,如命令行应用程序。这会让新手在阅读文档时产生困惑。记住,在 Go 语言里,命令是指任何可执行程序。作为对比,包更常用来指语义上可导入的功能单元。
让我们来实际体验一下。首先,在$GOPATH/src/hello/目录里创建一个叫 hello.go 的文件,并输入代码清单 3-1 里的内容。这是个经典的“Hello World!”程序,不过,注意一下包的声明以及 import
语句。
代码清单 3-1 经典的“Hello World!”程序
01 package main
02
03 import "fmt" ●―――― fmt 包提供了完成格式化输出的功能。
04 05 func main() { 06 fmt.Println("Hello World!") 07 }
获取包的文档 别忘了,可以访问 http://golang.org/pkg/fmt/ 或者在终端输入
godoc fmt
来了解更多关于fmt
包的细节。
保存了文件后,可以在$GOPATH/src/hello/目录里执行命令 go build
。这条命令执行完后,会生成一个二进制文件。在 UNIX、Linux 和 Mac OS X 系统上,这个文件会命名为 hello,而在 Windows 系统上会命名为 hello.exe。可以执行这个程序,并在控制台上显示“Hello World!”。
如果把这个包名改为 main
之外的某个名字,如 hello
,编译器就认为这只是一个包,而不是命令,如代码清单 3-2 所示。
代码清单 3-2 包含 main
函数的无效的 Go 程序
01 package hello
02
03 import "fmt"
04
05 func main(){
06 fmt.Println("Hello, World!")
07 }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论