3.2 包与导入
写好 import,程序才能用到标准库、本模块其它包以及第三方模块。依赖从哪来、版本谁管由 3.1 Go mod 模块管理 负责;本节聚焦:导入语法、包名与路径的关系、初始化顺序、模块模式下的解析习惯。
一、包与导入路径
- 包(package):同一目录下的
.go文件,首行用同一个package xxx声明;编译单元以目录为单位。 - 导入路径(import path):
import "..."里的字符串。在 Go Modules 下,一般是模块路径 + 子目录(如github.com/gin-gonic/gin),标准库则短路径(如fmt)。 - 包名与目录名:习惯上目录名与
package名一致,但可以不同。例如目录名叫utilset,文件里却是package utils,则import仍写模块下的路径,调用时要用utils.导出名,而不是目录名utilset。
go
import "example.com/myapp/utilset" // 导入路径对应目录 utilset
func f() {
utils.SomeFunc() // ✅ 与 package 声明一致
// utilset.SomeFunc() // ❌ 包名不是 utilset 时无法编译
}读别人代码时以各文件顶部的 package 行为准。
二、单行导入与分组导入
路径必须用双引号。多包时用分组形式更清晰(gofmt 会整理顺序):
go
import "fmt"
import (
"fmt"
"sync"
)三、别名导入
用于避免包名冲突、缩短长路径或与本地变量名冲突:
go
import (
"crypto/rand"
mrand "math/rand"
)
import pathpkg "path"四、点导入(.)
go
import . "fmt"
func main() {
Println("hello") // 等价于 fmt.Println,但不写包名
}会把被导入包的导出符号放进当前文件作用域,易与本地标识符冲突,可读性也差。除极小示例外不推荐。
五、匿名导入(空白导入 _)
只执行包的 init 副作用(如注册数据库驱动、编解码器),不在代码里直接引用包名:
go
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)编译器要求 import 被使用;_ 表示「仅为副作用导入」。
六、init 与包初始化顺序
1. init 的特点
- 签名固定为
func init(),无参数、无返回值。 - 不能被业务代码调用。
- 同一包、同一文件可写多个
init,按源文件名字典序、文件内自上而下依次执行(以当前 Go 语言规范为准)。 - 在
init之前,会先完成包级常量、变量的初始化(依赖解析顺序由声明与初始化表达式决定)。
2. 跨包顺序(依赖图)
若 main → A → B(main import A,A import B),则先完成 B 的包级变量与 init,再 A,最后 main 的包级变量与 init,最后 main.main。概括为:被依赖方先于依赖方初始化。
3. 小示例
go
package main
import "fmt"
func init() { fmt.Println("init1:", a) }
func init() { fmt.Println("init2:", a) }
var a = 10
func main() { fmt.Println("main:", a) }典型输出中,两个 init 里 a 已为 10,随后进入 main。
七、模块模式下的路径解析
日常在 3.1 已用 go mod init 的项目里,应使用 import 的模块路径,不要使用相对路径(如 ./foo):Go Modules 不支持这类相对导入作为常规做法。
解析依赖时(简化理解):
- 标准库(如
fmt):来自GOROOT。 - 若使用
-mod=vendor且存在vendor/:优先从vendor解析(与 3.1 中go mod vendor配套)。 - 其它模块:来自模块缓存(通常
$GOPATH/pkg/mod或等价位置),版本由go.mod锁定。
旧式 仅 GOPATH、govendor 的搜索优先级只需做背景了解;新项目以 模块 + go.mod 为准即可。
八、小结
| 要点 | 说明 |
|---|---|
| 路径 vs 包名 | import 用路径;代码里用 package 声明的名字 访问导出符号。 |
| 导入形式 | 普通、别名、.(慎用)、_ 副作用导入。 |
init | 自动执行,注意跨包依赖顺序与包级变量初始化先后。 |
| 模块项目 | 相对路径 import 避免使用;依赖版本交给 3.1 Go mod。 |
更多官方说明可在终端执行 go help importpath、go help modules 查阅。