Need help understanding exporting variables in Go

huangapple go评论90阅读模式
英文:

Need help understanding exporting variables in Go

问题

我了解从Go之旅中得知,大写变量意味着可以被导出,而结构体中的小写变量则不能被导出。但是我想要实现另外一种效果。

在Java中,我可以定义一个名为Adult的类,如下所示:

class Adult {
    private int age;

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

在Go语言中,我了解可以通过以下方式实现类似的效果:

// adult.go
package main

type Adult struct {
    age int // 将其设为小写,因此是私有的。我希望没有人会修改它。
}

func (a *Adult) setAge(x int) { // 只有setter方法
    if x >= 18 {
        a.age = x
    }
}

然而,在我的main.go中,我可以这样做:

package main

import "fmt"

func (a *Adult) getAge() *int { // 这应该是不可能的?
    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() // 我该如何防止别人这样做?
    *this_age_should_be_hidden = 5
    fmt.Println(*temp.getAge())
}

这就引出了我提出这个问题的原因。如果我们将变量设为小写,那有什么意义呢?我们总是可以在结构体上定义方法来暴露未导出的变量吗?这不是在一开始就违背了将其设为小写的初衷吗?

另外,如何用Go的方式实现我在上面的Java版本中所做的事情?如何确保结构体的某些字段在类外部不能被设置为无效值?

英文:

I understand from the Go tour that upper case variables are meant to be exported, while lower case variables in a struct are not exported. But I am trying to achieve something else.

In Java, I could define a class Adult, like so

class Adult
{
    private int age;

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

In GoLang, I understand I could do something similar like so:

//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
    }
}

However, I can do this in my 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())
}

That brings me to the title of this question. If we lower case our variables, what is the point? Can we always define methods on the struct which would expose unexported variables? Doesn't that defeat the purpose of lowercasing it, in the first place?

Also, what would be the Go way to achieve what I have done in the Java version above? How can I ensure that certain fields of my structs are not set to invalid values outside the class?

答案1

得分: 3

私有字段将在包内部可用。

考虑以下情况,基于您的示例,但将Adult放在自己的person包中:

package person

type Adult struct {
    age int //将其小写,因此是私有的。我不希望有人擅自更改它。
}

func (a *Adult) setAge(x int) { //仅为设置器
    if x >= 18 {
        a.age = x
    }
}

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

package main

func main() {
    var a person.Adult{}
    a.setAge(10)         //不可能 - 方法是私有的
}

如果您需要使用设置器,您可能希望将它们大写,以便对外部包开放,这样您就可以这样做:

package main

func main() {
    var a person.Adult{}
    a.SetAge(10)        //可用的方法
}
英文:

Private fields will be available within the package.

Consider the following, based on your example, but placing Adult inside its own person package :

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
    }
}

Should an adult be created inside person package, one could set his age. However, one would not be able to set the age from an external package :

package main

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

If you need to use setters, you might want to capitalize them to open them to external packages so that you can do :

package main

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

huangapple
  • 本文由 发表于 2021年10月13日 20:30:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/69555629.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定