Golang中为什么非内部包可以暴露内部实现?

Golang中为什么非内部包可以暴露内部实现? 我发现了一个奇怪的行为,不确定这是否是一个错误。在向 GitHub - golang/go: The Go 编程语言 提交问题之前,我想听听你们是否认为这是一个错误。假设我的模块中有两个包:

  • foo/internal/bar:此包导出了 type MyBar struct {...}
  • foo:此包导入了 foo/internal/bar 并定义了 func Foo() bar.MyBar {...}

在这种“包布局”下,go vet 没有任何报错。我也可以从另一个模块使用 Foo 函数,例如,打印其返回值。我认为不应该允许从一个非内部函数返回一个内部结构体,因为这规避了内部结构体通常的限制。

你们是否也认为这是一个错误,或者当前的行为有什么合理的理由?


更多关于Golang中为什么非内部包可以暴露内部实现?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

这是对 为什么非内部包可以暴露内部实现? 的意外重复。请在另一个主题中进行讨论。

更多关于Golang中为什么非内部包可以暴露内部实现?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是一个符合 Go 语言设计的行为,不是错误。internal 目录的访问限制是基于导入路径的,而不是基于类型的可见性。

当你在 foo 包中导入 foo/internal/bar 时,这是被允许的,因为 foofoo/internal/bar 在同一个模块内(共享 foo 前缀)。internal 的限制只适用于模块外部的包。

示例代码:

// foo/internal/bar/bar.go
package bar

type MyBar struct {
    Value string
}

// foo/foo.go
package foo

import "foo/internal/bar"

func Foo() bar.MyBar {
    return bar.MyBar{Value: "internal"}
}

// 其他模块可以这样使用
package main

import (
    "fmt"
    "foo"
)

func main() {
    b := foo.Foo()
    fmt.Println(b.Value) // 输出: internal
}

go vet 不会报错是因为这种用法完全符合 Go 的语言规范。internal 机制的目的是防止模块外部的代码直接导入内部包,而不是限制内部类型在模块内部的传播。一旦 foo 包导出了返回 bar.MyBar 的函数,这个类型就通过 foo 包的公共 API 暴露给了外部调用者。

这种设计允许模块内部有更灵活的组织结构,同时仍然通过 internal 目录保护了实现细节不被外部直接导入。

回到顶部