在Effective Go中,clearly stated表示在未导出字段的情况下(以小写字母开头),getter方法应具有相同的字段名称,但以大写字母开头;他们提供的示例是owner
作为字段,Owner
作为方法。他们明确建议不要在getter方法名称前面使用Get
。
我经常遇到需要为JSON编组导出字段,与ORM一起使用或其他与反射相关的目的的情况(IIRC反射可以读取但不能修改未导出的字段),因此需要调用我的字段{ {1}}在上面的示例中,因此无法使用Owner
方法。
是否有一种惯用的命名方式可以解决这种情况?
编辑:以下是我遇到的具体示例:
Owner
type User struct {
Username string `db:"username" json:"username"`
// ...
}
// code in this package needs to do json.Unmarshal(b, &user), etc.
答案 0 :(得分:3)
如果导出字段,请不要使用getter和setter。这只会混淆界面。
如果你需要一个getter或setter,因为它做某事(验证,格式化等),或者因为你需要struct来满足一个接口,那么就不要导出底层字段!
如果为了JSON,数据库访问等需要导出的字段,和需要getter / setter,那么使用两个结构,一个导出,一个私有,并定义一个自定义JSON封送器(或db访问方法)对公共的一个:
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,
})
}
答案 1 :(得分:0)
我会在考虑@Flimzy的答案后得出答案,这很有道理。
基本思想是让一个结构具有可用于编组的导出字段,另一个结构的唯一目的是提供满足所需接口的方法。
这不需要自定义编组代码,并且为每个结构提供了明确的含义,IMO:
type user struct {
Username string `json:"username"`
}
type ExportedUser struct {
// EDIT: explicitly doing "user *user" instead of just doing "*user"
// helps avoid confusion between between field names and methods
user *user
}
func (u ExportedUser) Username() string { return u.user.Username }
func main() {
fmt.Printf("Test: %q", ExportedUser{user: &user{Username: "joe"}}.Username())
}
以上是user
还是User
的问题对我来说有点不清楚 - 因为在Go模板中使用该类型可能是有意义的,例如{{euser.User.SomeOtherField}}
因此,如果需要,可以访问所有字段。无论如何,上面的答案都以相同的方式运作。