Idiomatic way to do conversion/type assertion on multiple return values in Go

Solution 1:

You can't do it in a single line. Your temporary variable approach is the way to go.

By the way, is it called casting when it comes to interfaces?

It is actually called a type assertion. A type cast conversion is different:

var a int
var b int64

a = 5
b = int64(a)

Solution 2:

func silly() (interface{}, error) {
    return "silly", nil
}

v, err := silly()
if err != nil {
    // handle error
}

s, ok := v.(string)
if !ok {
    // the assertion failed.
}

but more likely what you actually want is to use a type switch, like-a-this:

switch t := v.(type) {
case string:
    // t is a string
case int :
    // t is an int
default:
    // t is some other type that we didn't name.
}

Go is really more about correctness than it is about terseness.

Solution 3:

Or just in a single if:

if v, ok := value.(migrater); ok {
    v.migrate()
}

Go will take care of the cast inside the if clause and let you access the properties of the casted type.

Solution 4:

template.Must is the standard library's approach for returning only the first return value in one statement. Could be done similarly for your case:

func must(v interface{}, err error) interface{} {
    if err != nil {
        panic(err)
    }
    return v
}

// Usage:
str2 := must(twoRet()).(string)

By using must you basically say that there should never be an error, and if there is, then the program can't (or at least shouldn't) keep operating, and will panic instead.