【问题标题】:How to access unexported package private variable如何访问未导出的包私有变量
【发布时间】:2021-07-19 04:17:03
【问题描述】:

如下代码

package internal

var internalVar = "foobar"

如何从另一个包(如package main)访问此internalVar

internal 包被放置在第三方库中,我的应用程序需要使用一些原始作者不愿意公开为公共 API 的私人信息。

【问题讨论】:

  • 你不能,至少不能直接,这就是未导出变量的全部意义所在。您最多可以将导出的 getter func 添加到内部包中,然后使用它。
  • package internal 在您的模块中还是在其他模块中?为什么需要从package main 访问它?为什么internalVar 未导出?您应该澄清一下,否则我们可能不得不将该问题标记为不清楚...

标签: go


【解决方案1】:

正如@mkopriva 提到的,内部变量不应该在它们的包之外访问。 Go 明确地将其作为强制可访问性的一种方式,如果未导出内部 var,则不应访问它。再说一遍:不要这样做,这很糟糕,我们不喜欢它。当您需要在包之外访问它们时,请始终导出您的变量。

上面说的那个巨大的免责声明,有一些方法可以访问内部变量:指针、程序集和链接名。我会在后面解释,因为它是最简单的:

Go 编译器有一个名为//go:linkname 的漂亮指令。它基本上链接不同包之间的变量/函数。来自文档:

//go:linkname localname [importpath.name]

此特殊指令不适用于其后的 Go 代码。相反,//go:linkname 指令指示编译器使用“importpath.name”作为源代码中声明为“localname”的变量或函数的目标文件符号名称。如果省略“importpath.name”参数,则该指令使用符号的默认目标文件符号名称,并且仅具有使其他包可以访问该符号的效果。因为这个指令可以颠覆类型系统和包的模块化,所以它只在导入了“unsafe”的文件中启用。

这意味着您可以使用它来访问其他未导出的函数和变量,如下所示:

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/internal.go

package internal

var message string = "Hello!"

func SayHello() {
    println(message)
}

您将看到输出遵循我们已覆盖的 "abc" 值。

不要这样做,除非你真的,真的需要修补一些东西。

【讨论】:

    猜你喜欢
    • 2011-03-02
    • 1970-01-01
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    相关资源
    最近更新 更多