调用golang结构函数给出"不能引用未导出的字段或方法"

0xA*_*xAX 38 struct pointers go

我有一个像这样的golang结构:

type MyStruct struct {
    Id    string
}
Run Code Online (Sandbox Code Playgroud)

和功能:

func (m *MyStruct) id() {
   // doing something with id here
}
Run Code Online (Sandbox Code Playgroud)

我还有另一个这样的结构:

type MyStruct2 struct {
    m *MyStruct
}
Run Code Online (Sandbox Code Playgroud)

现在我有一个功能:

func foo(str *MyStruct2) {
    str.m.id()
}
Run Code Online (Sandbox Code Playgroud)

但是我在编译时遇到错误:

str.m.id undefined (cannot refer to unexported field or method mypackage.(*MyStruct)."".id
Run Code Online (Sandbox Code Playgroud)

如何正确调用此功能?

谢谢

One*_*One 90

来自http://golang.org/ref/spec#Exported_identifiers:

可以导出标识符以允许从另一个包访问它.如果两者都导出标识符:

  1. 标识符名称的第一个字符是Unicode大写字母(Unicode类"Lu"); 和
  2. 标识符在包块中声明,或者是字段名称或方法名称.

所以基本上只有以大写字母开头的函数/变量才能在包外使用.

例:

type MyStruct struct {
    id    string
}

func (m *MyStruct) Id() {
   // doing something with id here
}

//then

func foo(str *MyStruct2) {
    str.m.Id()
}
Run Code Online (Sandbox Code Playgroud)

  • 这是f王问题!`所以基本上只有以大写字母开头的函数/变量---才能在`之外使用.谢谢! (15认同)

Ina*_*mus 5

如果更改MyStruct.IdMyStruct.id,您将不再能够访问它来初始化MyStruct2,因为,id将可以访问只能通过自己的包(first)。

这是因为MyStructMyStruct2位于不同的程序包中。


要解决此问题,您可以执行以下操作:

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,
    }
}
Run Code Online (Sandbox Code Playgroud)

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"),
    })
}
Run Code Online (Sandbox Code Playgroud)