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

huangapple go评论82阅读模式
英文:

Comparing the return values of methods with multiple return values

问题

考虑以下示例方法,每个方法都返回三个整数:

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

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

我想知道这些方法的返回值是否相同,类似于这样:

equal := a() == b()

然而,这段代码无法编译,因为编译器期望的是单个值:

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

我目前的解决方法是创建一个与这些方法具有相同签名的自定义类型,然后创建第三个函数来进行检查:

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)

但我希望有一个更通用的解决方案。

英文:

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.

答案1

得分: 1

这可能不是你想要的准确答案,但是如果你返回结构体而不是三个未命名的整数,你可以直接比较它们。例如:

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())
    // 输出:
    //   true
}

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

英文:

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.

答案2

得分: 1

使用结构体

你可以通过将结果存储在可比较的结构体值中来稍微改进它:

type Result struct {
    a, b, c int
}

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

使用数组

或者你可以使用数组(数组与切片不同,数组是可比较的),虽然这样做不会更短,但你不需要为此定义新类型:

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

通用解决方案(使用reflect

可以使用reflect包构建一个通用解决方案。基本上,它调用两个函数,并比较所有的结果值。省略了错误检查!

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
}

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

Go Playground上尝试这些代码。

英文:

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.

huangapple
  • 本文由 发表于 2015年10月19日 16:57:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/33210377.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定