引入

代码越写越多,全塞在一个文件里肯定不行。Go 用(package)把代码按功能组织在一起,方便复用和管理。每个 .go 文件都必须属于一个包,包和包之间通过导入来使用对方的代码。

正文

定义

定义

(package)是 Go 代码的组织单元,把代码按功能组织在一起,方便复用和管理。每个 .go 文件的第一行必须声明所属包名。大写开头的标识符是导出的(外部可用),小写开头的标识符是未导出的(仅包内可用)。

语法

// 声明包(每个文件第一行必须有)
package mypackage
 
// 导入其他包
import "fmt"
import "math/rand"
 
// 批量导入
import (
    "fmt"
    "os"
    "strings"
)
 
// 导出函数(大写开头)
func Hello() string {
    return "hello"
}
 
// 未导出函数(小写开头)
func helper() string {
    return "helper"
}

例子

创建自定义包

project/
├── main.go
└── greeting/
    └── greeting.go
// greeting/greeting.go
package greeting
 
func Hello(name string) string {
    return "Hello, " + name
}
 
func hi(name string) string {
    return "Hi, " + name // 小写开头,外部不能调用
}
// main.go
package main
 
import (
    "fmt"
    "project/greeting"
)
 
func main() {
    fmt.Println(greeting.Hello("Alice"))
    // fmt.Println(greeting.hi("Alice")) // 编译错误:未导出
}

大写开头的 Hello 能被外部包调用,小写开头的 hi 只能在 greeting 包内部使用。

导入路径

// 标准库包
import "fmt"
import "os"
import "net/http"
 
// 第三方包
import "github.com/gin-gonic/gin"
 
// 项目内部包
import "project/internal/utils"

标准库直接用包名导入,第三方包和项目内部包用完整路径

包的别名

import (
    "fmt"
    myrand "math/rand"
)
 
func main() {
    fmt.Println(myrand.Intn(100))
}

别名 包路径 的语法给导入的包起个别名,解决包名冲突或起一个更短的名字。

点导入

import . "fmt"
 
func main() {
    Println("hello") // 不需要 fmt. 前缀
}

点导入后可以直接用包里的标识符,不需要加包名前缀。不推荐使用,会降低代码可读性。

空白导入

import _ "net/http/pprof"

空白导入 _ 不直接使用包的内容,但会执行包的 init() 函数。常用于注册驱动启动副作用

init() 函数

package config
 
import "fmt"
 
var AppName string
 
func init() {
    AppName = "MyApp"
    fmt.Println("config 包初始化完成")
}

init() 函数在包被导入时自动执行,不需要手动调用。常用来做包的初始化工作。

init() 执行顺序

package main
 
import "fmt"
 
var x = initVar()
 
func initVar() int {
    fmt.Println("变量初始化")
    return 1
}
 
func init() {
    fmt.Println("init 函数")
}
 
func main() {
    fmt.Println("main 函数")
}
// 输出顺序:
// 变量初始化
// init 函数
// main 函数

执行顺序:变量初始化 → init()main()。同一个包里可以有多个 init() 函数,按文件名字母序执行。

常见写法

写法说明
package name声明包名(文件第一行)
import "path"导入包
import ( "a"; "b" )批量导入
import alias "path"导入并起别名
import . "path"点导入(不推荐)
import _ "path"空白导入(只执行 init)
func init()包初始化函数
大写开头导出(外部可用)
小写开头未导出(仅包内可用)

特点

  • 每个 .go 文件第一行必须声明包名
  • 大写开头的标识符是导出的,小写开头的未导出
  • 包名通常和目录名一致,用小写短单词
  • import 路径是目录路径,不是包名
  • init() 自动执行,适合做包的初始化
  • 执行顺序:变量初始化 → init()main()
  • 同一个包可以有多个文件,同包内标识符互相可见
  • main 包是可执行程序的入口,只有 main 包有 main() 函数

理解

包就是把代码按功能分到不同抽屉里,大写的东西能给别人用,小写的自己留着。import 告诉 Go 去哪个抽屉拿东西,init() 在打开抽屉时自动跑一次。包是 Go 组织代码的基础,理解了包才能看懂 Go 项目是怎么管理的。

引出

包解决了代码组织问题,但项目大了以后,怎么管理外部依赖?不同项目用了不同版本的第三方包怎么办?接下来看 Go 模块,学习 Go 的依赖管理方案。