可见性
导出规则是什么? 导出标识符与非导出标识符有何区别?
- 导出标识符: 首字符为 Unicode 大写字母,且声明于包块中,或作为字段名、方法名时可导出;局部变量大写不会自动成为包 API;
- 非导出标识符: 不满足导出条件的包级声明、字段或方法只供包内使用;下划线及无大小写之分的首字符也不满足大写条件;
- 可见性粒度: package, 而不是文件;
package user
type Profile struct {
Name string // 首字母大写字段,package 外可见
age int // 首字母小写字段,仅 package 内可见
}
- 封装用途: 未导出字段可以强制调用方通过方法维护约束;对外暴露一个字段意味着调用方可以直接读取或修改它,设计 API 时应考虑这一责任;
// 下列声明属于 user 包。
func (p *Profile) SetAge(age int) {
if age >= 0 {
p.age = age // 外部调用者通过方法修改未导出字段
}
}
// 包外可以调用 p.SetAge(18),不能直接写 p.age。
internal 目录怎样限制包的导入范围?
- internal: Go 工具链强制执行的导入边界,只有位于该
internal父目录所对应目录树内的代码可以导入其包; - 边界示例:
project/internal/service允许project/cmd/server导入,不允许目录树外的其他项目直接导入; - 目录约定入口:
cmd、pkg与分层示例统一见项目结构,它们没有 internal 的强制导入限制;
project/
├── internal/service/ # 内部实现
├── cmd/server/ # 在 project 树内,可以导入 service
└── client/ # 在 project 树内,可以导入 service
other/ # 在 project 树外,不可以导入 service