匿名结构的意外返回

时间:2015-11-20 16:25:41

标签: struct go

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

;WITH    myCTE
    AS ( SELECT   T1.Year ,
                T1.Month ,
                T1.CarNumberID ,
                T1.CarDepartedDateTime ,
                T1.CarDepartedNumberID ,
                LEAD(T1.CarDepartedDateTime) OVER ( ORDER BY T1.id ) AS [NextCarDepartureTime] ,
                LEAD(T1.CarNumberID) OVER ( ORDER BY T1.id ) AS [NextCarNumberID]
        FROM     Test T1
        )
SELECT  * ,
    DATEDIFF(HOUR, CarDepartedDateTime, NextCarDepartureTime) AS TurnAroundTime
FROM    myCTE;

我收到以下错误:

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

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:4)

使用"真正"匿名结构返回值

如果你想使用匿名结构返回值,那将会看起来很丑陋。

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

当你试图写这个:

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一样引用它们,就像它们在{{1}中定义一样}}。将其定义为常规字段也可以。

答案 1 :(得分:3)

The Go Programming Language Specification

Keywords

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

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