Code like below
package internal
var internalVar = "foobar"
How can i access this internalVar
from another package like package main
?
internal
package is placed in a 3rd party library, and my application needs to use some private info which original author is not willing to expose as a public API.
As @mkopriva mentioned, internal variables should not be accessed outside their packages at all. Go explicitly does that as a way to enforce accessibility and if the internal var is not exported, then it shouldn't be accessed. Again: don't do this, it's bad Go and we don't like it. Always export your variables when you need to access them outside your packages.
That huge disclaimer above being said, there are ways on how you can access internal variables: pointers, assembly and linkname. I'll explain the later since it's the easiest one:
Go compiler has this nifty directive called //go:linkname
. It basically links variables/functions between different packages. From the documentation:
//go:linkname localname [importpath.name]
This special directive does not apply to the Go code that follows it. Instead, the
//go:linkname
directive instructs the compiler to use “importpath.name” as the object file symbol name for the variable or function declared as “localname” in the source code. If the “importpath.name” argument is omitted, the directive uses the symbol's default object file symbol name and only has the effect of making the symbol accessible to other packages. Because this directive can subvert the type system and package modularity, it is only enabled in files that have imported "unsafe".
That means that you can use it to access otherwise unexported functions and variables, with something like this:
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)
}
You will see that the output respects the "abc"
value we've overwritten.
Don't do this unless you really, really needs to monkey patch something.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With