Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go语言内部包--控制包成员的对外暴露 #58

Open
kevinyan815 opened this issue Mar 30, 2021 · 0 comments
Open

Go语言内部包--控制包成员的对外暴露 #58

kevinyan815 opened this issue Mar 30, 2021 · 0 comments

Comments

@kevinyan815
Copy link
Owner

kevinyan815 commented Mar 30, 2021

问题

Go 语言中的软件包推荐按照:组织名/项目名 的形式安排软件包的文件目录结构,一般「项目名」文件目录下还会按照功能、抽象约定、具体实现等维度再划分一些子目录。在 Go 语言里包的导入路径不同则被判定为不同的包,所以同一个软件包项目下的「功能一」包依赖「功能二」包里的成员时,那么成员必须是导出成员才能被「功能一」包引用。但是这样一来,其他项目或者其他组织的代码也就都可以使用这个导出的成员了,假如包里的一些成员我们只想在指定的包之间共享而不想对外暴露该怎么办呢? Go 语言内部包这个特性可以让我们实现这个目标。

内部包

Go语言1.4版本后增加了 Internal packages 特征用于控制包的导入,即internal package只能被特定的包导入。

内部包的规范约定:导出路径包含internal关键字的包,只允许internal的父级目录及父级目录的子包导入,其它包无法导入。

示例

.
|-- resources
|   |-- internal
|   |   |-- cpu
|   |   |   `-- cup.go
|   |   `-- mem
|   |       `-- mem.go
|   |-- input
|   |   |-- input.go
|   `-- mainboard.go
|-- prototype
|   `-- professional.go 
|-- go.mod
|-- go.sum 

如上包结构的程序,resources/internal/cpuresources/internal/mem只能被resources包及其子包resources/input中的代码导入,不能被prototype包里的代码导入。当在prototype包的代码中导入并调用resources/internal/cpu包的函数时,编译器根据文件的目录结构判断出来prototype包相对于被导入的包是外部包,所以整个程序会编译失败,报类似下面的错误:

use of internal package /resources/internal/cpu not allowed

总结

internal/ 是 go 编译器在编译程序时可以识别的特殊目录名,除非两个包都具有相同的祖先,否则它将阻止另一个包导入internal/目录下的包。因此,我们将internal/目录中的软件包称为内部包。

要为项目创建内部包,只需将包文件放在名为internal/的目录中。当 go 编译器在导入路径中看到带有internal/的软件包的导入时,它将验证导入包的程序文件是否位于internal/目录的父级目录,或父级目录的子目录中。

举例来说导入路径为 /a/b/c/internal/d/e/f 的包,只能被位于/a/b/c目录或者其子目录中的代码引入,而不能被位于/a/b/e 目录或其子目录中的代码引用。

https://dave.cheney.net/2019/10/06/use-internal-packages-to-reduce-your-public-api-surface

https://blog.learngoprogramming.com/special-packages-and-directories-in-go-1d6295690a6b

https://www.bitlogs.tech/2019/10/go%E8%AF%AD%E8%A8%80%E5%86%85%E9%83%A8%E5%8C%85internal/

@kevinyan815 kevinyan815 changed the title 用Internal Package 内部包减少不必要公开的API 用内部包减少不必要公开的内部成员 Apr 11, 2021
@kevinyan815 kevinyan815 changed the title 用内部包减少不必要公开的内部成员 Go语言内部包--控制包成员的对外暴露 Apr 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant