跳到主要内容

package

Go语言是使用包来组织源代码的,包(package)是多个 Go 源码的集合,是一种高级的代码复用方案。Go语言中为我们提供了很多内置包,如 fmt、os、io 等。任何源代码文件必须属于某个包,同时源码文件的第一行有效代码必须是package pacakgeName 语句,通过该语句声明自己所在的包。

Go语言的包借助了目录树的组织形式,一般包的名称就是其源文件所在目录的名称,虽然Go语言没有强制要求包名必须和其所在的目录名同名,但还是建议包名和所在目录同名,这样结构更清晰。

1.1、包的基本使用

导入包的语法:

import "包的路径"    // 双引号

导入包路径规则:

Go 程序首先在 GOROOT/src 目录中寻找包目录,如果没有找到,则会去 GOPATH/src 目录中继续寻找。比如 fmt 包是位于 GOROOT/src 目录的 Go 语言标准库中的一部分,它将会从该目录中导入。

目录结构

image-20220917232517408

db

package db

import "fmt"

func HandleMySQL() {
fmt.Println("操作MySQL数据库")
}
package db

import "fmt"

func HandleRedis() {
fmt.Println("操作redis数据库")
}

api包

package api

import "fmt"
import "mysite/db"

func RestfulAPI() {
db.HandleMySQL()
fmt.Println("RestfulAPI:MySQL数据接口")
}
package api

import "fmt"
import "mysite/db"

func RpcAPI() {
db.HandleRedis()
fmt.Println("RpcAPI:redis数据接口")
}

main

package main

import "mysite/api"

func main() {
// db.HandleMySQL()
// db.HandleRedis()

api.RestfulAPI()
api.RpcAPI()
}
提示

1、包名一般是小写的,见名知意,包名中不能包含- 等特殊符号。

提示

2、包名规范上要和所在的目录同名,也可以不同。比如package api改为package newApi,代码改动为

package main

import newApi "mysite/api"

func main() {
newApi.RestfulAPI()
newApi.RpcAPI()
}
提示

3、包名为 main 的包为应用程序的入口包,编译不包含 main 包的源码文件时不会得到可执行文件。

提示

4、一个文件夹下的所有源码文件只能属于同一个包,同样属于同一个包的源码文件不能放在多个文件夹下。

提示

5、一个包下的不同文件不能含有同名函数。

提示

6、如果想在一个包中引用另外一个包里的标识符(如变量、常量、类型、函数等)时,该标识符必须是对外可见的(public),在Go语言中只需要将标识符的首字母大写就可以让标识符对外可见了。

提示

7、环境变量GO111MODULE=off: go env -w GO111MODULE=off

提示

8、将mysite剪切到src外的任何位置,都会导包失败。

1.2、包的导入格式

// 一次导入多个包
import (
"fmt"
"mysite/api"
)

// 设置包的别名
import F "fmt"

// 省略引用格式
import . "mysite/api"
RestfulAPI()

// 匿名导入 :在引用某个包时,如果只是希望执行包初始化的 init 函数,而不使用包内部的数据时,可以使用匿名引用格式
import _ "包名"
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)

1.3、包的加载顺序

init()函数会在每个包完成初始化后自动执行,并且执行优先级比main函数高。

init 函数通常被用来:

  • 对变量进行初始化

  • 检查/修复程序的状态

  • 注册

  • 运行一次计算

提示

注意:

提示

1、一个包可以有多个 init 函数,包加载时会执行全部的 init 函数,但并不能保证执行顺序,所以不建议在一个包中放入多个 init 函数,将需要初始化的逻辑放到一个 init 函数里面。

提示

2、包不能出现环形引用的情况,比如包 a 引用了包 b,包 b 引用了包 c,如果包 c 又引用了包 a,则编译不能通过。

提示

3、包的重复引用是允许的,比如包 a 引用了包 b 和包 c,包 b 和包 c 都引用了包 d。这种场景相当于重复引用了 d,这种情况是允许的,并且 Go 编译器保证包 d 的 init 函数 只会执行一次

提示

4、init()函数没有参数也没有返回值。 init()函数在程序运行时自动被调用执行,不能在代码中主动调用它。

image-20210324210805734