什么是package
package起到组织源代码的作用,并实现了命名空间的管理。在go语言中,每一个源文件都属于package的一部分,在文件头部用package声明所属包的名称:
package main
import (
"fmt"
)
func main() {
fmt.println("hello world!")
}
包由一个或多个保存在同一目录下(不含子目录)的源码文件组成。包的用途类似命名空间,是成员作用域和访问权限的边界。
- 包名与目录名无关,不要求保持一致
- 包名通常使用单数形式。源文件必须使用utf-8格式,否则会导致编译出错
包名 | 描述 |
---|---|
main | 可执行入口(入口函数mian.main) |
all | 标准库以及gopath中能找到的所有包 |
std | 标准库及工具链 |
cmd | 标准库及工具链 |
documentation | 存储文档信息,无法导入(和目录名无关) |
所有成员在包内均可访问,无论是否在同一份源码文件中。但只有名称首字母大写的为可导出成员,在包外可视(该规则适用于全局变量、全局常量、类型、结构字段、函数和方法)。不过通过指针转换的方式可以绕开该权限限制:
例如如下的包结构中:
├── main.go
├── school
└── student.go
school/student.go中定义了一个不能在包外可视的类型student,它有两个成员属性,name和age,都是可以包外可视的。该源码文件中同时还定义了一个函数newstudent,返回一个指向student的指针:
package school
type student struct {
name string
age int
}
func newstudent(name string, age int) *student {
return &student{
name: name,
age: age,
}
}
在main.go中,虽然不能对student结构可视,但是通过调用newstudent函数,我们可以绕开该限制:
package main
import (
"fmt"
"go-exercise/school"
)
func main() {
stu := school.newstudent("bob", 13)
fmt.printf("%t, %s, %d\n", stu, stu.name, stu.age)
// output: *school.student, bob, 13
}
init函数用于package的初始化操作。每一个package内可以定义多个init函数,这些函数可以分布在package中的每一个源码文件中。但编译器不保证这些init函数的执行次序。
package main
import (
"fmt"
)
func init() {
fmt.println("in init function...")
}
func main() {
fmt.println("in main function...")
// outputs:
// in init function...
// in main function...
}