【问题标题】:Invoking struct function gives "cannot refer to unexported field or method"调用结构函数给出“不能引用未导出的字段或方法”
【发布时间】:2014-08-20 16:41:57
【问题描述】:

我有一个类似这样的结构:

type MyStruct struct {
    Id    string
}

和功能:

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

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

type MyStruct2 struct {
    m *MyStruct
}

现在我有一个函数:

func foo(str *MyStruct2) {
    str.m.id()
}

但我在编译时遇到错误:

str.m.id undefined (cannot refer to unexported field or method mypackage.(*MyStruct)."".id

如何正确调用这个函数?

【问题讨论】:

    标签: pointers struct go


    【解决方案1】:

    来自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()
    }
    

    【讨论】:

    • 这是他妈的问题! So basically only functions / variables starting with a ---capital letter--- would be usable outside the。谢谢!
    • 有趣的是没有其他帖子谈论这个。他们都提出了不同的方法来绕过这个问题。谢谢。
    • 我同意这一点。资本化问题。 Go 有点自以为是
    • “有趣的是没有其他帖子谈论这个。” - 这是因为大多数人(错误地)认为这是常识,而忘记为第一次学习此知识的观众量身定制他们的答案。
    【解决方案2】:

    如果您将MyStruct.Id 更改为MyStruct.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,
        }
    }
    

    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"),
        })
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-20
      • 1970-01-01
      • 2017-12-26
      • 1970-01-01
      • 2020-12-28
      • 2017-07-28
      • 1970-01-01
      相关资源
      最近更新 更多