具有“真正的”匿名结构返回值
如果你想使用匿名结构返回值,那看起来会非常难看。
为什么?因为当你定义返回类型时,你必须描述匿名结构。当你写一个return
语句,您必须提供返回值,该值将是一个结构文字。匿名结构的结构文字也必须描述该结构!
当你尝试这样写时:
func (p *Project) OmitUsername() *struct {
// return somethig
}
此语法不是您想象的那样:它不包含结构定义。基本上在你的例子中第一个{
是匿名结构定义的左括号,并且not函数体的左括号。也正因如此,接下来的return
被解释为位于匿名结构定义内部,这是无效语法,这也正是错误消息所指出的内容("syntax error: unexpected return"
).
它应该看起来像这样:
func (p *Project) OmitUsername() *struct {
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
} {
// And now here comes the return statement
}
如果您还添加了必须重复匿名结构定义的 return 语句:
func (p *Project) OmitUsername() *struct {
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
} {
return &struct {
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
}{p.Id, p.Alias, p.Data, p.Scheme}
}
是的,它很丑。您可以通过使用命名返回值而不返回指针来使其变得更简单,因为指针的零值是nil
,并且要返回某些内容,您必须对其进行初始化,这还涉及重复匿名结构!如果您使用非指针、命名返回值,您将立即获得匿名结构体的值,并且不必再次重复匿名结构体定义,只需为其字段赋值即可:
func (p *Project) OmitUsername2() (ret struct {
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
}) {
ret.Id = p.Id
ret.Alias = p.Alias
ret.Data = p.Data
ret.Scheme = p.Scheme
return
}
使用它们:
p := Project{"Bob", 1, "bobie", nil, nil}
fmt.Println(p.OmitUsername())
fmt.Println(p.OmitUsername2())
输出(在去游乐场 http://play.golang.org/p/YLSTOwDjsC):
&{1 bobie <nil> <nil>}
{1 bobie <nil> <nil>}
还是丑...
对于另一个命名类型,使用嵌入
...最好是提供另一个命名类型来返回,而不是匿名结构。您可以利用嵌入为了使这个解决方案实用且简短:
type BaseProject struct {
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
}
type Project struct {
BaseProject
Username string
}
func (p *Project) OmitUsername() BaseProject {
return p.BaseProject
}
使用它:
p := Project{BaseProject{1, "bobie", nil, nil}, "Bob"}
fmt.Println(p.OmitUsername())
输出(在去游乐场 http://play.golang.org/p/QUv9SO-E1X):
{1 bobie <nil> <nil>}
Note:
嵌入并不是真正必要的,但这样嵌入类型的字段(BaseProject
)将会被提升,所以你可以像这样参考它们p.Id
就好像它们被定义在Project
。将其定义为常规字段也可行。