在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
包是结构化代码的一种方式:每个程序都由包(通常简称为 pkg)的概念组成,可以使用自身的包或者从其它包中导入内容。 如同其它一些编程语言中的类库或命名空间的概念,每个 Go 文件都属于且仅属于一个包。一个包可以由许多以 你必须在源文件中非注释的第一行指明这个文件属于哪个包,如: 一个应用程序可以包含不同的包,而且即使你只使用 main 包也不必把所有的代码都写在一个巨大的文件里:你可以用一些较小的文件,并且在每个文件非注释的第一行都使用 标准库 在 Go 的安装文件里包含了一些可以直接使用的包,即标准库。在 Windows 下,标准库的位置在 Go 根目录下的子目录 Go 的标准库包含了大量的包(如:fmt 和 os),但是你也可以创建自己的包。 如果想要构建一个程序,则包和包内的文件都必须以正确的顺序进行编译。包的依赖关系决定了其构建顺序。 属于同一个包的源文件必须全部被一起编译,一个包即是编译时的一个单元,因此根据惯例,每个目录都只包含一个包。 如果对一个包进行更改或重新编译,所有引用了这个包的客户端程序都必须全部重新编译。 Go 中的包模型采用了显式依赖关系的机制来达到快速编译的目的,编译器会从后缀名为 如果
这种机制对于编译大型的项目时可以显著地提升编译速度。 每一段代码只会被编译一次 一个 Go 程序是通过
如果需要多个包,它们可以被分别导入: import "fmt"
import "os"
或: import "fmt"; import "os"
但是还有更短且更优雅的方法(被称为因式分解关键字,该方法同样适用于 const、var 和 type 的声明或定义): import (
"fmt"
"os"
)
它甚至还可以更短的形式,但使用 gofmt 后将会被强制换行: import ("fmt"; "os")
当你导入多个包时,导入的顺序会按照字母排序。 如果包名不是以 导入包即等同于包含了这个包的所有的代码对象。 除了符号 包通过下面这个被编译器强制执行的规则来决定是否将自身的代码对象暴露给外部文件: 可见性规则 当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的 代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 private )。 (大写字母可以使用任何 Unicode 编码的字符,比如希腊文,不仅仅是 ASCII 码中的大写字母)。 因此,在导入一个外部包后,能够且只能够访问该包中导出的对象。 假设在包 pack1 中我们有一个变量或函数叫做 Thing(以 T 开头,所以它能够被导出),那么在当前包中导入 pack1 包,Thing 就可以像面向对象语言那样使用点标记来调用: 因此包也可以作为命名空间使用,帮助避免命名冲突(名称冲突):两个包中的同名变量的区别在于他们的包名,例如 你可以通过使用包的别名来解决包名之间的名称冲突,或者说根据你的个人喜好对包名进行重新设置,如: 示例 4.2 alias.go package main
import fm "fmt" // alias3
func main() {
fm.Println("hello, world")
}
注意事项 如果你导入了一个包却没有使用它,则会在构建程序时引发错误,如 包的分级声明和初始化 你可以在使用 Go 程序的一般结构下面的程序可以被顺利编译但什么都做不了,不过这很好地展示了一个 Go 程序的首选结构。这种结构并没有被强制要求,编译器也不关心 main 函数在前还是变量的声明在前,但使用统一的结构能够在从上至下阅读 Go 代码时有更好的体验。 所有的结构将在这一章或接下来的章节中进一步地解释说明,但总体思路如下:
示例 4.4 gotemplate.go package main
import (
"fmt"
)
const c = "C"
var v int = 5
type T struct{}
func init() { // initialization of package
}
func main() {
var a int
Func1()
// ...
fmt.Println(a)
}
func (t T) Method1() {
//...
}
func Func1() { // exported function Func1
//...
}
Go 程序的执行(程序启动)顺序如下:
|
请发表评论