Go Getter 方法与字段,正确命名

Bra*_*ody 7 getter naming-conventions go

在 Effective Go 中,明确规定在未导出字段(以小写字母开头)的情况下,getter 方法应具有相同的字段名称,但以大写开头;他们给出的例子是owner作为一个字段和Owner一个方法。他们明确建议不要Get在 getter 方法名称前使用。

我经常遇到需要导出字段以进行 JSON 编组、与 ORM 或其他反射相关用途(IIRC 反射可以读取但不能修改未导出的字段)的情况,因此需要Owner在上面的示例中调用我的字段因此不能有Owner方法。

是否有一种惯用的命名方式可以解决这种情况?

编辑:这是我遇到的一个具体例子:

type User struct {
    Username string `db:"username" json:"username"`
    // ...
}

// code in this package needs to do json.Unmarshal(b, &user), etc.
Run Code Online (Sandbox Code Playgroud)

.

// BUT, I want code in other packages to isolate themselves from
// the specifics of the User struct - they don't know how it's
// implemented, only that it has a Username field.  i.e.
package somethingelse

type User interface {
    Username() string
}

// the rest of the code in this other package works against the
// interface and is not aware of the struct directly - by design,
// because it's important that it can be changed out without
// affecting this code
Run Code Online (Sandbox Code Playgroud)

Fli*_*mzy 11

如果您的字段已导出,请不要使用 getter 和 setter。这只会混淆界面。

如果您需要 getter 或 setter 因为它执行某些操作(验证、格式化等),或者因为您需要结构来满足接口,那么不要导出底层字段!

如果为了 JSON、数据库访问等需要导出字段,并且需要 getter/setter,那么使用两个结构,一个导出的和一个私有的,并在公开一:

type jsonFoo struct {
    Owner string `json:"owner"`
}

type Foo struct {
    owner string
}

func (f *Foo) SetOwner(username string) {
    // validate/format username
    f.owner = username
}

func (f *Foo) Owner() string {
    return f.owner
}

func (f *Foo) MarshalJSON() ([]byte, error) {
    return json.Marshal(jsonFoo{
        Owner: f.owner,
    })
}
Run Code Online (Sandbox Code Playgroud)