Let's say I have this:
type Donut string
type Muffin string
func getPastry () (interface{}, error) {
// some logic - this is contrived
var d Donut
d = "Bavarian"
return d, nil
}
Is it possible to reduce this to one line:
p, err := getPastry()
thisPastry := p.(Donut)
In other words, something like this, which does not compile:
thisPastry, err := getPastry().(Donut, error)
Not that having two lines of code to get the "generic" and type it is a big deal, but it just feels wasteful and un-simple to me, and that usually means I'm missing something obvious :-)
You can't. Best you can do is write a helper function (and do the type assertion in that):
func getDonut(p interface{}, err error) (Donut, error) {
return p.(Donut), err
}
And then it becomes a one-line:
d, err := getDonut(getPastry())
Or you may even "incorporate" the getPastry()
call in the helper function:
func getDonutPastry() (Donut, error) {
p, err := getPastry()
return p.(Donut), err
}
And then calling it (an even shorter one-liner):
d, err := getDonutPastry()
Note:
Of course if the value returned by getPastry()
is not of dynamic type Donut
, this will be a runtime panic. To prevent that, you may use the special form of the type assertion:
v, ok := x.(T)
Which yields an additional untyped boolean value. The value of ok
is true
if the assertion holds. Otherwise it is false
and the value of v
is the zero value for type T
. No run-time panic occurs in this case.
Safe versions of the helper functions using the special form could look like this (they return an error rather than panic):
func getDonut2(p interface{}, err error) (Donut, error) {
if d, ok := p.(Donut); ok {
return d, err
} else {
return "", errors.New("Not a Donut!")
}
}
func getDonutPastry2() (Donut, error) {
p, err := getPastry()
if d, ok := p.(Donut); ok {
return d, err
} else {
return "", errors.New("Not a Donut!")
}
}
See related questions:
Return map like 'ok' in Golang on normal functions
Go: multiple value in single-value context
Short answer: It's not possible.
Long answer:
It will be more readable and understandable by more people as there are no long lines chaining together many things.
In your example, I'm assuming you will have to test for an error and then check for a Muffin etc. To make it super clear which types you expect and what to do with them, you can do a type switch:
thisPastry, err := getPastry()
if err != nil { ... }
switch v := thisPastry.(type) {
case Donut:
fmt.Println(v)
case Muffin:
fmt.Println(v, "mmm!")
default:
// some kind of error?
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With