Go 的 package 是编译单元而非运行时模块,同一目录下所有 .go 文件必须声明相同 package 名;能否被外部引用取决于标识符首字母是否大写,与包名无关;import 路径是模块路径而非文件路径;init() 按依赖图顺序执行,易引发隐式依赖问题;包别名仅作用于当前文件。

Go 里 package 不是“模块”,而是编译单元
Go 的 package 和 Python 的 import 或 JS 的 export 本质不同:它不控制运行时的命名空间,而是在编译期划分代码边界和依赖关系。一个目录下所有 .go 文件必须声明相同的 package 名,否则 go build 直接报错:found packages main and utils in /path/to/dir。
常见误区是以为改个 package name 就能“导出”变量——实际能否被外部引用,只取决于标识符首字母是否大写(即是否 exported),和包名本身无关。
-
package main是可执行程序的入口,必须且只能有一个func main() -
package mylib是库包,不能有main函数,编译后不生成二进制,只供其他包import - 同目录下多个
.go文件必须用相同package声明,哪怕只是空文件
import 路径不是文件路径,而是模块路径 + 子目录
Go 的 import "fmt" 或 import "github.com/user/repo/subpkg" 指向的是 GOROOT、GOPATH/src 或 go.mod 定义的模块根下的相对路径,不是你本地磁盘的绝对路径。比如项目结构是:
myproject/
├── go.mod
└── internal/
└── db/
└── conn.go // package db
那么在别处 import 它,写的是 import "myproject/internal/db"(前提是 go.mod 里 module myproject),而不是 import "./internal/db"——后者会报错:use of internal package not allowed(如果跨模块)或 invalid import path(因为 Go 不支持相对导入)。
立即学习“go语言免费学习笔记(深入)”;
本书全面介绍PHP脚本语言和MySOL数据库这两种目前最流行的开源软件,主要包括PHP和MySQL基本概念、PHP扩展与应用库、日期和时间功能、PHP数据对象扩展、PHP的mysqli扩展、MySQL 5的存储例程、解发器和视图等。本书帮助读者学习PHP编程语言和MySQL数据库服务器的最佳实践,了解如何创建数据库驱动的动态Web应用程序。
-
标准库包如
fmt、net/http直接 import,无需路径前缀 - 第三方包以域名开头,如
github.com/gorilla/mux,对应磁盘上$GOPATH/pkg/mod/github.com/gorilla/mux@v1.8.0/ - 本地子包必须在
go.mod定义的 module 路径下,且 import 路径必须完整匹配模块名 + 子目录
init() 函数只在包加载时执行一次,且顺序受依赖图约束
每个包可定义零个或多个 func init(),它们在 main() 执行前自动调用,但不接受参数、无返回值。关键点在于:执行顺序由包依赖决定,而非文件先后或 import 顺序。
例如 A 包 import B,B import C,则一定是 C → B → A 的 init() 顺序;同一包内多个 init() 按源文件字典序执行(a.go 先于 b.go)。这容易引发隐式依赖问题:比如 B 的 init() 初始化了一个全局 DB 连接,A 在自己的 init() 里就去用,看似合理,但一旦 B 被间接 import(比如通过另一个包),顺序可能变化,导致 panic。
- 避免在
init()中做耗时操作或强依赖外部服务 - 不要假设同一包内多个
init()的执行顺序(除非控制文件名) - 更推荐显式初始化函数,如
db.Init(),由main()明确调用
包名和 import 别名不是一回事,别名只影响当前文件作用域
包声明里的 package http 是该包的默认本地名,仅用于本包内部引用自身导出符号(如 http.Client)。而 import 语句中的别名(如 import json2 "encoding/json")只改变当前文件里对该包的引用名,不影响包内定义或其它文件。
典型误用是以为 import m "mylib" 后,别人 import 你的包时也要用 m ——完全错误。别人 import 时仍写 import "myproject/mylib",使用时也写 mylib.DoSomething(),和你的别名 m 毫无关系。
- 别名主要用于解决命名冲突,如
import sql "database/sql"和import "github.com/lib/pq"都含sql相关类型 - 用
.别名(import . "fmt")会让所有导出符号进入当前作用域,极易造成命名污染,生产代码禁止使用 - 包名建议简短、小写、无下划线,如
http、yaml、cli,避免和标准库或常用第三方重名
init() 的隐式依赖,这三处最容易在协作或重构时出问题,尤其当项目从无模块迁移到 go mod 后,旧路径写法会直接失效。









