如何访问未导出的包私有变量
代码如下
package internal
var internalVar = "foobar"
我如何internalVar从另一个包访问它package main?
internal 包放置在第 3 方库中,我的应用程序需要使用一些原始作者不愿意公开为公共 API 的私人信息。
回答
正如@mkopriva 提到的,内部变量根本不应该在它们的包之外访问。Go 明确地这样做是为了强制执行可访问性,如果未导出内部变量,则不应访问它。再说一遍:不要这样做,Go 很糟糕,我们不喜欢它。当您需要在包外访问变量时,请始终导出它们。
上面说了那个巨大的免责声明,有很多方法可以访问内部变量:指针、程序集和链接名。我会在后面解释,因为它是最简单的:
Go 编译器有一个漂亮的指令叫做//go:linkname. 它基本上链接不同包之间的变量/函数。从文档:
//go:linkname localname [importpath.name]这个特殊指令不适用于它后面的 Go 代码。相反,该
//go:linkname指令指示编译器使用“importpath.name”作为源代码中声明为“localname”的变量或函数的目标文件符号名称。如果省略“importpath.name”参数,则该指令使用符号的默认目标文件符号名称,并且仅具有使其他包可以访问该符号的效果。因为这个指令可以颠覆类型系统和包模块化,所以它只在导入了“不安全”的文件中启用。
这意味着您可以使用它来访问其他未导出的函数和变量,如下所示:
main.go
package main
import (
"temp/test-access-internal/internal"
_ "unsafe"
)
//go:linkname message temp/test-access-internal/internal.message
var message string
func main() {
message = "abc"
println(message)
internal.SayHello()
}
内部/internal.go
package internal
var message string = "Hello!"
func SayHello() {
println(message)
}
您将看到输出尊重"abc"我们覆盖的值。
不要这样做,除非你真的、真的需要修补一些东西。