0%

go语言包(package)的基本概念

基本概念

  • 源码文件的第一行有效代码必须是 package pacakgeName 语句,通过该语句声明自己所在的包
  • 一般包的名称就是其源文件所在目录的名称,虽然Go语言没有强制要求包名必须和其所在的目录名同名,但还是建议包名和所在目录同名,这样结构更清晰
  • 包可以定义在很深的目录中,包名的定义是不包括目录路径的,但是包在引用时一般使用全路径引用。比如在GOPATH/src/a/b/ 下定义一个包 c。在包 c 的源码中只需声明为package c,而不是声明为package a/b/c,但是在导入 c 包时,需要带上路径,例如import "a/b/c"
  • 包名一般是小写的,使用一个简短且有意义的名称
  • 包名一般要和所在的目录同名,也可以不同,包名中不能包含 - 等特殊符号
  • 包一般使用域名作为目录名称,这样能保证包名的唯一性,比如 GitHub 项目的包一般会放到 GOPATH/src/github.com/userName/projectName 目录下
  • 包名为 main 的包为应用程序的入口包,编译不包含 main 包的源码文件时不会得到可执行文件
  • 一个文件夹下的所有源码文件只能属于同一个包,同样属于同一个包的源码文件不能放在多个文件夹下

包的导入

  • import 导入语句通常放在源码文件开头包声明语句的下面
  • 导入的包名需要使用双引号包裹起来
  • 包名是从 GOPATH/src/ 后开始计算的,使用 / 进行路径分隔
  • 包的引用路径有两种写法,分别是全路径导入和相对路径导入,相对路径只能用于导入 GOPATH 下的包,标准包的导入只能使用全路径导入

包的引用格式

  1. 标准引用格式
package main
import "fmt"

func main() {
    fmt.Println("Hello world")
}
  1. 自定义别名引用格式
package main
import F "fmt"

func main() {
    // 使用F.来代替标准引用格式的fmt.
    F.Println("Hello world")
}
  1. 省略引用格式
package main
import . "fmt"

func main() {
    // 不用加前缀fmt.
    Println("Hello world")
}
  1. 匿名引用格式
package main
import (
    // 在引用某个包时,如果只是希望执行包初始化的 init 函数,而不使用包内部的数据时,可以使用匿名引用格式
    // 一个包可以有多个 init 函数,包加载时会执行全部的 init 函数,但并不能保证执行顺序
    _ "database/sql"
    "fmt"
)
func main() {
    fmt.Println("Hello world")
}

包加载

包加载

  • 包初始化程序从 main 函数引用的包开始,逐级查找包的引用,直到找到没有引用其他包的包,最终生成一个包引用的有向无环图
  • Go 编译器会将有向无环图转换为一棵树,然后从树的叶子节点开始逐层向上对包进行初始化
  • 单个包的初始化过程如上图所示,先初始化常量,然后是全局变量,最后执行包的 init 函数