Go语言 Package 和 Import 学习笔记
Go语言 Package 和 Import 学习笔记
查看结论直接跳转到7,8,9即可
本博客主要记录:同一个目录下的go文件都得是一个package里面的,不允许同一个目录的的go文件属于第二个包。也就是一个目录对应一个package,而不同目录下的想要调用当前目录的go文件里面的代码必须使用import才可以进行调用
注:大小写控制的包内和包外是否可以调用,不管大小写,包内都随便调用,如果是大写,那么你在别的包使用import之后可以调用,如果是小写,那么在包外就无法被调用了
一、核心问题:同一个 package 的文件能否互相调用?
1.1 问题场景
假设
hello1.go是package main,hello2.go也是package main,那么在hello1.go中能否直接调用hello2.go中的函数?这两个文件是否属于同一个作用域?
1.2 答案
是的,可以!
如果两个文件满足以下条件:
- 声明相同的包名(如
package main) - 在同一个目录下
那么:
- ✅ 可以直接调用对方的函数
- ✅ 属于同一个包,共享同一个命名空间
1.3 代码示例
1 | // hello1.go |
1 | // hello2.go |
1.4 运行方式
1 | # ❌ 错误:只运行一个文件,会报错 "undefined: SayHello" |
二、Go 的 Package 规则详解
2.1 核心规则
| 规则 | 说明 |
|---|---|
| 同目录 = 同包 | 同一个目录下的所有 .go 文件必须声明相同的包名 |
| 包内共享 | 同一个包内的所有代码共享命名空间,可以互相访问 |
| 大小写控制导出 | 首字母大写 = 可被其他包访问;首字母小写 = 仅包内访问 |
2.2 作用域示意图
1 | ┌─────────────────────────────────────────┐ |
2.3 注意事项
1. 同一目录不能有不同包名
1 | // ❌ 错误示例 |
2. 函数不能重复定义
其实就是在同一个作用域里面不能定义两个一样的函数
1 | // ❌ 两个文件都定义了同名函数 |
三、与 C++ 头文件机制的对比
3.1 整体对比
| 特性 | C++ | Go |
|---|---|---|
| 代码组织 | 头文件(.h) + 源文件(.cpp) | 包(package) |
| 声明可见性 | 头文件声明 | 首字母大小写 |
| 引用方式 | #include "xxx.h" |
import "xxx" |
| 编译单位 | 单个 .cpp 文件 | 整个包 |
| 符号导出 | 所有声明都可见 | 大写开头才导出 |
| 链接 | 手动管理 .lib 或 .o |
自动处理 |
3.2 同一个项目内文件共享的对比
C++ 方式:需要头文件声明
1 | // ========== hello2.h ========== |
Go 方式:同一个包内直接用
1 | // ========== hello2.go ========== |
对比总结:
| C++ | Go |
|---|---|
同目录下的 .cpp 文件互不知道 |
同目录下的 .go 文件(同包)自动共享 |
必须用 #include 引入头文件 |
不需要,同包直接用 |
| 头文件 = 声明的桥梁 | 无需桥梁,编译器自动处理 |
3.3 引用其他目录/模块代码的对比
C++ 方式:
1 | // ========== math_utils/math_utils.h ========== |
Go 方式:
1 | // ========== math_utils/add.go ========== |
对比总结:
| C++ | Go |
|---|---|
#include "xxx.h" 引入声明 |
import "xxx" 引入整个包 |
| 头文件里声明的都能用 | 只有大写开头的能用 |
链接时需要 .lib 或 .o 文件 |
自动链接,无需手动管理 |
3.4 完整对比图
1 | ┌─────────────────────────────────────────────────────────────────┐ |
四、Package 和 Import 的区别
4.1 核心概念
| Go 概念 | 作用 | C++ 类比 |
|---|---|---|
| package | 定义”我是谁”(属于哪个包) | namespace + 编译单元 |
| import | 引入”别人是谁”(使用其他包) | #include + using |
4.2 package = 定义身份
Go:
1 | // hello.go |
C++ 类比:
1 | // hello.cpp |
| Go | C++ |
|---|---|
package myutils |
namespace myutils { ... } |
| 定义这个文件属于哪个包 | 定义这些代码属于哪个命名空间 |
| 每个文件必须声明 | 可选,不是必须的 |
4.3 import = 引入别人
Go:
1 | // main.go |
C++ 类比:
1 | // main.cpp |
| Go | C++ |
|---|---|
import "xxx" |
#include "xxx.h" + 链接 |
| 引入整个包的符号 | 引入头文件的声明 |
| 自动链接 | 需要手动链接 .lib 或 .o |
4.4 核心区别总结
package = 定义身份(我是谁)
• 写在文件开头
• 声明这个文件属于哪个包
• 类似 C++ 的 namespace,但更强(目录必须对应)
import = 引入别人(我要用谁)
• 引入其他目录的包
• 类似 C++ 的 #include + using
• 但只能用大写开头的符号
类比:
package → “我是中国人”(定义身份)
import → “我要用美国货”(引入外部资源)
五、不同目录下的情况分析
5.1 场景 A:三个文件在同一个目录,都是 package main
1 | myproject/ |
1 | // hello1.go |
结论:同目录 + 同包名 = 直接用,不需要 import
5.2 场景 B:hello3.go 在另一个目录(错误示例)
1 | myproject/ |
1 | // main/hello1.go |
问题:
main包是程序入口,不能被其他包 import- 如果想让代码被其他包使用,必须放在非 main 包里
5.3 场景 C:正确做法 - 抽取公共代码到独立包
1 | myproject/ |
1 | // myutils/hello1.go |
5.4 场景总结
| 场景 | 能否调用 | 原因 |
|---|---|---|
| 同目录 + 同包名 | ✅ 直接调用 | 同一个包,共享作用域 |
| 同目录 + 不同包名 | ❌ 编译错误 | Go 要求同目录必须同包名 |
| 不同目录 + import “main” | ❌ 编译错误 | main 包不能被 import |
| 不同目录 + 抽取到独立包 | ✅ import 后调用 | 正确做法 |
六、常见错误示例
6.1 错误:import 自己所在的包
1 | // ❌ 错误示例 |
6.2 错误:import main 包
1 | // ❌ 错误示例 |
6.3 错误:同目录不同包名
1 | // ❌ 错误示例 |
七、Go 的核心规则总结
Go 的 package/import 规则:
import 只能引入【其他包】,不能引入自己所在的包
main 包是程序入口,不能被其他包 import
同目录 = 必须同包名 = 不需要 import = 直接用
不同目录 = 不同包 = 需要 import = 通过包名调用
大写开头 = 可被其他包使用(导出)
小写开头 = 只能包内使用(私有)
八、与 C++ 的核心差异总结
| 特性 | C++ | Go |
|---|---|---|
| 同目录文件共享 | 需要头文件声明 | 同包自动共享 |
| 使用其他模块 | #include "xxx.h" |
import "xxx" |
| 符号可见性 | 头文件里写了就能用 | 大写=导出,小写=私有 |
| 编译链接 | 手动管理 .o .lib |
自动处理 |
| 循环依赖 | 头文件可以循环 include | 禁止循环 import |
| main 能否被引用 | 可以 | 不能被 import |
九、总结
Go Package 机制速查表
• 每个文件必须声明 package
• 同目录必须同包名
• 类似 C++ 的 namespace
【import = 引入别人】
• 只能引入其他目录的包
• 不能 import 自己所在的包
• 不能 import main 包
• 类似 C++ 的 #include + using
【大小写控制可见性
• 大写开头 = 导出(可被其他包使用)
• 小写开头 = 私有(只能包内使用)
这一条不止针对函数,而是针对所有的标识符,比如函数,变量,结构体等等
【同包 = 同作用域】
• 同目录 + 同包名 = 直接用,不需要 import
• 不同目录 = 需要 import + 通过包名调用
同一个目录下的go文件都得是一个package里面的,不允许同一个目录的的go文件属于第二个包。
也就是一个目录对应一个package,而不同目录下的想要调用当前目录的go文件里面的代码必须使用import才可以进行调用










