比较具有多个返回值的方法的返回值

Considering the following example methods, each of which returns three integers:

func a() (int, int, int) {...}

func b() (int, int, int) {...}

I want to know if the return values of these methods are the same, something like this:

equal := a() == b()

However, this doesn't compile because the compiler is expecting a single value:

my_file.go:14: multiple-value a() in single-value context
my_file.go:14: multiple-value b() in single-value context

My current work around is to create a custom type with the same signature as the methods, and then create a third function to do the checking:

type multiReturnFunc func() (int, int, int)
func a() (int, int, int) {...}
func b() (int, int, int) {...}

func checkMultiReturns(a, b multiReturnFunc) bool {
    a1, a2, a3 := a()
    b1, b2, b3 := b()
    return a1 == b1 && a2 == b2 && a3 == b3
}

...

equal := checkMultiReturns(a, b)

But I would like to have a more general solution.

This might not be exactly what you want, but if instead of returning three unnamed ints you return structs, you can compare them directly. E.g.

type XYZ struct{ X, Y, Z int }

func f() XYZ { return XYZ{1, 2, 3} }
func g() XYZ { return XYZ{1, 2, 3} }

func main() {
    fmt.Println(f() == g())
    // Output:
    //   true
}

Playground: http://play.golang.org/p/zFXPqPjTtZ.

With structs

You can slightly improve it by storing the result in values of a struct which are comparable:

type Result struct {
    a, b, c int
}

And using it:

p, q := Result{}, Result{}
p.a, p.b, p.c = a()
q.a, q.b, q.c = b()
fmt.Println(p == q)

With arrays

Or you can use arrays (arrays are also comparable unlike slices), although this won't be shorter, but you don't need a new type for this:

x, y := [3]int{}, [3]int{}
x[0], x[1], x[2] = a()
y[0], y[1], y[2] = b()
fmt.Println(x == y)

General solution (using reflect)

A general solution may be constructed using the reflect package. This basically calls both functions, and compares all the result values. Error checks omitted!

func check(v1, v2 reflect.Value) bool {
    r1 := v1.Call(nil)
    r2 := v2.Call(nil)
    if len(r1) != len(r2) {
        return false
    }

    for i, a := range r1 {
        if a.Interface() != r2[i].Interface() {
            return false
        }
    }

    return true
}

And using it:

fmt.Println(check(reflect.ValueOf(a), reflect.ValueOf(b)))

Try these on the Go Playground.