Invoking struct function gives "cannot refer to unexported field or method"
From http://golang.org/ref/spec#Exported_identifiers:
An identifier may be exported to permit access to it from another package. An identifier is exported if both:
- the first character of the identifier's name is a Unicode upper case letter (Unicode class "Lu"); and
- the identifier is declared in the package block or it is a field name or method name.
So basically only functions / variables starting with a capital letter would be usable outside the package.
Example:
type MyStruct struct {
id string
}
func (m *MyStruct) Id() {
// doing something with id here
}
//then
func foo(str *MyStruct2) {
str.m.Id()
}
If you change MyStruct.Id
to MyStruct.id
:
- You'll no longer be able to access it to initialize
MyStruct2
. -
id
will be accessible only through its own package: thefirst
package. - Because:
MyStruct
andMyStruct2
are in different packages.
To solve the problem you can do this:
Package first
:
package first
type MyStruct struct {
// `id` will be invisible outside of `first` package
// because, it starts with a lowercase letter
id string
}
// `Id()` is visible outside to `first` package
// because, it starts with an uppercase letter
func (m *MyStruct) Id() string {
return m.id
}
// Create a constructor function to return `*MyStruct`
func NewMyStruct(id string) *MyStruct {
return &MyStruct{
id: id,
}
}
Package second
:
package second
// Import MyStruct's package
import "first"
type MyStruct2 struct {
// If you don't use `m` here as in your question,
// `first.MyStruct` will be promoted automatically.
//
// So, you can reach its methods directly,
// as if they're inside `MyStruct2`
*first.MyStruct
}
// You can use `Id()` directly because it is promoted
// As if, inside `MyStruct2`
func foo(str *MyStruct2) {
str.Id()
}
// You can initialize `MyStruct2` like this:
func run() {
foo(&MyStruct2{
MyStruct: first.NewMyStruct("3"),
})
}