With "truly" anonymous struct return value
If you want to use an anonymous struct return value, that's gonna look really ugly.
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
}
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"
).
It should look like this:
func (p *Project) OmitUsername() *struct {
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
} {
// And now here comes the return statement
}
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}
}
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
}
Using them:
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>}
Still ugly...
With another named type, using embedding
...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
}
Using it:
p := Project{BaseProject{1, "bobie", nil, nil}, "Bob"}
fmt.Println(p.OmitUsername())
Output (try this on the Go Playground):
{1 bobie <nil> <nil>}
Note:
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.