首页 > 解决方案 > 需要帮助理解 Go 中的导出变量

问题描述

我从 Go 之旅中了解到,大写变量是要导出的,而结构中的小写变量不会被导出。但我正在努力实现其他目标。

在 Java 中,我可以定义一个类Adult,就像这样

class Adult
{
    private int age;

    void setAge(int x)
    {
        if (x >= 18)
            this.age = x;
    }
}

在 GoLang 中,我知道我可以做类似的事情:

//adult.go
package main

type Adult struct {
    age int //Made this lowercase, therefore private. I expect no one messes with this.
}

func (a *Adult) setAge(x int) { //Setter only
    if x >= 18 {
        a.age = x
    }
}

但是,我可以在我的main.go

package main

import "fmt"

func (a *Adult) getAge() *int { // This shouldn't be possible?
    return &a.age
} 

func main() {
    var temp *Adult = new(Adult)
    temp.setAge(24)
    fmt.Println(*temp.getAge())

    var this_age_should_be_hidden = temp.getAge() //How do I prevent someone from doing this?
    *this_age_should_be_hidden = 5
    fmt.Println(*temp.getAge())
}

这让我想到了这个问题的标题。如果我们将变量小写,那有什么意义呢?我们可以总是在结构上定义会暴露未导出变量的方法吗?首先,这不是破坏了小写它的目的吗?

另外,实现我在上面的 Java 版本中所做的事情的 Go 方法是什么?如何确保我的结构的某些字段未设置为类外的无效值?

标签: oopgoinvariants

解决方案


包中将提供私有字段。

根据您的示例考虑以下内容,但将其放在Adult自己的person包中:

package person

type Adult struct {
    age int //Made this lowercase, therefore private. I expect no one messes with this.
}

func (a *Adult) setAge(x int) { //Setter only
    if x >= 18 {
        a.age = x
    }
}

如果在 person 包中创建一个成年人,可以设置他的年龄。但是,无法从外部包设置年龄:

package main

func main() {
    var a person.Adult{}
    a.setAge(10)         //impossible - method is private
}

如果您需要使用 setter,您可能希望将它们大写以将它们打开到外部包,以便您可以执行以下操作:

package main

func main() {
    var a person.Adult{}
    a.SetAge(10)        //available method
}


推荐阅读