为了账号安全,请及时绑定邮箱和手机立即绑定

匿名结构的意外返回

匿名结构的意外返回

Go
MMMHUHU 2021-11-22 18:23:57
我正在尝试实现一种方法,该方法返回基于原始结构的修改后的结构,例如: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任何帮助,将不胜感激。
查看完整描述

2 回答

?
哔哔one

TA贡献1854条经验 获得超8个赞

使用“真正的”匿名结构返回值

如果您想使用匿名结构体返回值,那看起来会非常难看。


为什么?因为在定义返回类型时,必须描述匿名结构体。当你写一个return语句时,你必须提供一个结构体的返回值。匿名结构的结构文字也必须描述结构!


当您尝试编写此内容时:


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

    // return somethig

}

这个语法不是你想的那样:它不包含结构定义。基本上在您的示例中,第一个{是匿名结构定义的左括号,而不是函数体的左括号。因此,后续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())

输出(在Go Playground上试试这些):


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

输出(在Go Playground上试试这个):


{1 bobie <nil> <nil>}

笔记:


嵌入并不是真正必要的,但是这样嵌入类型 ( BaseProject)的字段将被提升,因此您可以像p.Id在Project. 将其定义为常规字段也可以。


查看完整回答
反对 回复 2021-11-22
?
饮歌长啸

TA贡献1951条经验 获得超3个赞

以下关键字是保留的,不能用作标识符。


break        default      func         interface    select

case         defer        go           map          struct

chan         else         goto         package      switch

const        fallthrough  if           range        type

continue     for          import       return       var

.


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

}

struct 是保留关键字。


如果没有关于您正在尝试做什么的更多信息,就很难知道您想要什么,也许是这样的?


package main


import (

    "encoding/json"

)


type Scheme struct{}


type Project struct {

    Id     uint

    Alias  string

    Data   *json.RawMessage

    Scheme Scheme

}


type UserProject struct {

    Username string

    Project

}


func (u *UserProject) GetProject() *Project {

    return &u.Project

}


func main() {}


查看完整回答
反对 回复 2021-11-22
  • 2 回答
  • 0 关注
  • 154 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信