I was testing go's type visibility and received unexpected behavior when I exposed a private type through a public function:
package pak
type foo struct { // shoudn't be visible to any other package than pak
Bar string
}
func NewFoo(str string) *foo {
return &foo{str}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package main
import (
"fmt"
"pak"
)
func main() {
// these lines should be equivalent...
var f = pak.NewFoo("Hello, World!") // this works fine...
var f *pak.foo = pak.NewFoo("Hello, World!") // ERROR: cannot refer to unexported name pak.foo
fmt.Printf("%T\n", f)
fmt.Printf("%s\n", f.Bar) // how does it know about .Bar, if it can't see pak.foo?
}
Without explicitly declaring the type of f
, it prints:
*pak.foo
Hello, World!
but with *pak.foo
it fails to compile.
Why doesn't it fail in both cases?
(this question is sort of related, but it does not answer this question)
The valid statement
var f = pak.NewFoo("test")
gives you an anonymous, hidden address for the struct
foo
. You can't use it to read from or write to the struct
foo
outside the pak
package. You can, and usually will, use it to call a pak
package method. For example,
p := f.PakMethod()
The invalid statement
var f *pak.foo = pak.NewFoo("test")
attempts to obtain the address of the struct
foo
. If permitted, this would allow you to read from and write to the struct
foo
outside the pak
package.
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