Go 程序的基本结构和要素
示例 4.1 hello_world.go
package main
import "fmt"
func main() {
fmt.Println("hello, world")
}
1 包的概念、导入与可见性
包是结构化代码的一种方式:每个程序都由包(通常简称为 pkg)的概念组成,可以使用自身的包或者从其它包中导入内容。
如同其它一些编程语言中的类库或命名空间的概念,每个 Go 文件都属于且仅属于一个包。一个包可以由许多以 .go
为扩展名的源文件组成,因此文件名和包名一般来说都是不相同的。
你必须在源文件中非注释的第一行指明这个文件属于哪个包,如:package main
。package main
表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main
的包。
一个应用程序可以包含不同的包,而且即使你只使用 main 包也不必把所有的代码都写在一个巨大的文件里:你可以用一些较小的文件,并且在每个文件非注释的第一行都使用 package main
来指明这些文件都属于 main 包。如果你打算编译包名不是为 main 的源文件,如 pack1
,编译后产生的对象文件将会是 pack1.a
而不是可执行程序。另外要注意的是,所有的包名都应该使用小写字母。
标准库
在 Go 的安装文件里包含了一些可以直接使用的包,即标准库。在 Windows 下,标准库的位置在 Go 根目录下的子目录 pkg\windows_386
中;在 Linux 下,标准库在 Go 根目录下的子目录 pkg\linux_amd64
中(如果是安装的是 32 位,则在 linux_386
目录中)。一般情况下,标准包会存放在 $GOROOT/pkg/$GOOS_$GOARCH/
目录下。
Go 的标准库包含了大量的包(如:fmt 和 os),但是你也可以创建自己的包(第 8 章)。
如果想要构建一个程序,则包和包内的文件都必须以正确的顺序进行编译。包的依赖关系决定了其构建顺序。
属于同一个包的源文件必须全部被一起编译,一个包即是编译时的一个单元,因此根据惯例,每个目录都只包含一个包。
如果对一个包进行更改或重新编译,所有引用了这个包的客户端程序都必须全部重新编译。
Go 中的包模型采用了显式依赖关系的机制来达到快速编译的目的,编译器会从后缀名为 .o
的对象文件(需要且只需要这个文件)中提取传递依赖类型的信息。
如果 A.go
依赖 B.go
,而 B.go
又依赖 C.go
:
- 编译
C.go
,B.go
, 然后是A.go
. - 为了编译
A.go
, 编译器读取的是B.o
而不是C.o
.
这种机制对于编译大型的项目时可以显著地提升编译速度。
每一段代码只会被编译一次
一个 Go 程序是通过 import
关键字将一组包链接在一起。
import "fmt"
告诉 Go 编译器这个程序需要使用 fmt
包(的函数,或其他元素),fmt
包实现了格式化 IO(输入/输出)的函数。包名被封闭在半角双引号 ""
中。如果你打算从已编译的包中导入并加载公开声明的方法,不需要插入已编译包的源代码。
如果需要多个包,它们可以被分别导入:
import "fmt"
import "os"
或:
import "fmt"; import "os"
但是还有更短且更优雅的方法(被称为因式分解关键字,该方法同样适用于 const、var 和 type 的声明或定义):
import (
"fmt"
"os"
)
它甚至还可以更短的形式,但使用 gofmt 后将会被强制换行:
import ("fmt"; "os")
当你导入多个包时,导入的顺序会按照字母排序。
如果包名不是以 .
或 /
开头,如 "fmt"
或者 "container/list