意外返回匿名结构 [英] Unexpected return of anonymous struct

查看:57
本文介绍了意外返回匿名结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现一种基于原始结构返回修改后的结构的方法,例如:

I am trying to implement a method that returns a modified struct based on the original one, such as:

type Project struct {
    Username string           
    Id       uint      
    Alias    string           
    Data     *json.RawMessage 
    Scheme   Scheme          
}

func (p *Project) OmitUsername() *struct {

    return &struct {
        Id      uint         
        Alias   string   
        Data    *json.RawMessage
        Scheme  Scheme          
    }{
        p.Id,
        p.Alias,
        p.Data,
        p.Scheme
    })
}

然后出现以下错误:

models/project.go:22: syntax error: unexpected return 
models/project.go:24: non-declaration statement outside function body 
models/project.go:25: non-declaration statement outside function body 
models/project.go:25: syntax error: unexpected string literal, expecting semicolon or newline 
models/project.go:26: non-declaration statement outside function body

任何帮助将不胜感激.

推荐答案

具有真正的"匿名结构返回值

如果您要使用匿名结构返回值,那将看起来非常丑陋.

With "truly" anonymous struct return value

If you want to use an anonymous struct return value, that's gonna look really ugly.

为什么?因为定义返回类型时,必须描述匿名结构.而且,当您编写 return 语句时,必须提供返回值,该返回值将是结构文字.匿名结构的结构文字也必须描述该结构!

Why? Because when you define the return type, you have to describe the anonymous struct. And when you write a return statement, you have to provide the return value which will be a struct literal. A struct literal for an anonymous struct also has to describe the struct!

当您尝试编写此代码时:

When you attempt to write this:

func (p *Project) OmitUsername() *struct {
    // return somethig
}

此语法与您的想法不符:它不包含struct定义.基本上在您的示例中,第一个 {是匿名结构定义的左括号,而不是是函数主体的左括号.因此,后续的 return 被解释为位于无效语法的匿名结构定义中,这也正是错误消息所指出的内容(语法错误:意外返回" ).

This syntax is not what you think: it doesn't contain the struct definition. Basically in your example the first { is the opening bracket of the anonymous struct definition, and not the opening bracket of the function body. And as such, the subsequent return is interpreted as being inside the anonymous struct definition which is invalid syntax, this is exactly what the error message states too ("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语句,该语句必须重复匿名结构定义:

And if you also add the return statement which has to repeat the anonymous struct definition:

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 ,并且要返回某些内容,您必须对其进行初始化,这也涉及到重复匿名结构!如果使用名为返回值的非指针,则将立即获得匿名结构的值,而不必再次重复匿名结构定义,只需将值分配给其字段即可:

Yes, it's ugly. You can make it a little simpler by using named return value, and not returning a pointer, because zero value of pointers is nil, and to return something, you'd have to initialize it which would also involve repeating the anonymous struct! If you use a non-pointer, named return value, you will have a value of the anonymous struct right away, and you don't have to repeat the anonymous struct definition again, just assign values to its fields:

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())

输出(在进入游乐场上尝试这些):

Output (try these on the Go Playground):

&{1 bobie <nil> <nil>}
{1 bobie <nil> <nil>}

还是丑陋的...

...最好是提供另一个要返回的命名类型,而不是匿名结构.您可以利用 emdding 使该解决方案实用且简短:

...Best would be to provide another named type to return and not an anonymous struct. You may utilize embedding to make this solution practical and short:

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())

输出(在游乐场上尝试):

{1 bobie <nil> <nil>}

注意:

嵌入并不是真正必要的,但是通过这种方式,嵌入类型( BaseProject )的字段将得到提升,因此您可以像 p.Id 那样引用它们如果它们是在 Project 中定义的.将其定义为常规字段也可以.

Embedding is not really necessary, but this way the fields of the embedded type (BaseProject) will be promoted and so you can refer to them like p.Id as if they were defined in Project. Defining it as a regular field would also work.

这篇关于意外返回匿名结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆