Struct 意外返回匿名结构

Struct 意外返回匿名结构,struct,go,Struct,Go,我正在尝试实现一个方法,该方法返回基于原始结构的修改结构,例如: type Project struct { Username string Id uint Alias string Data *json.RawMessage Scheme Scheme } func (p *Project) OmitUsername() *struct {

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

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
任何帮助都将不胜感激。

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

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

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() {}
使用“真正”匿名结构返回值 如果你想使用匿名结构返回值,那看起来会很难看

为什么??因为在定义返回类型时,必须描述匿名结构。在编写
return
语句时,必须提供返回值,返回值将是一个struct literal。匿名结构的结构文字还必须描述该结构

当您尝试写入以下内容时:

func (p *Project) OmitUsername() *struct {
    // return somethig
}
此语法与您的想法不同:它不包含结构定义。基本上,在您的示例中,第一个
{
是匿名结构定义的开始括号,不是函数体的开始括号。因此,后续的
返回
被解释为在匿名结构定义内,这是无效语法,这也正是错误消息所述(
“语法错误:意外返回”

应该是这样的:

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
,若要返回某个值,您必须对其进行初始化,这还需要重复匿名结构!若您使用非指针,命名为返回值,您的值将为onymous结构,您不必再次重复匿名结构定义,只需为其字段赋值:

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())
输出(请在上尝试这些选项):

使用它:

p := Project{BaseProject{1, "bobie", nil, nil}, "Bob"}
fmt.Println(p.OmitUsername())
输出(在上尝试此操作):

{1 bobie}
注意:


实际上,嵌入不是必需的,但通过这种方式,嵌入类型的字段(
BaseProject
)将被提升,因此您可以像
p.Id
一样引用它们,就像它们是在
Project
中定义的一样。将其定义为常规字段也会起作用。

是的,这正是我想要的。为什么我首先要使用
struct
作为返回类型!?虽然您的答案非常清楚简洁,但我必须标记@icza的作为正确的一个,因为它更复杂,而且实际上首先提供了嵌入式类型解决方案。尽管如此,还是很感激。谢谢!你的回答非常复杂,为我打开了新的知识。因此,
结构
不是没有定义的类型!这是我以前从未知道过的。但是,嵌入式类型确实引入了更多的为
项目
声明新值时的简单性。
&{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())
{1 bobie <nil> <nil>}