跳到主要内容

可见性

导出规则是什么? 导出标识符与非导出标识符有何区别?​

  • 导出标识符: 首字符为 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