这两个变体之间有什么区别?

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

What's the difference between these two variants?

问题

我尝试编写自己的代码来学习如何在主函数中返回多个值:

package main

import "fmt"

func main() {
    fmt.Println("Enter a integer:")
    var I int
    fmt.Scanf("%d", &I)
    fmt.Println("Accepted:", I)

    O := half(I)
    fmt.Println("Returned:", O)
}

func half(N int) (int, bool) {
    var NA int
    NA = N / 2
    if NA%2 == 0 {
        fmt.Println("even")
        return NA, true
    } else {
        fmt.Println("odd")
        return NA, false
    }
}

然后出现错误:half.go|11| multiple-value half() in single-value context
然而,另一种变体是可以工作的:

package main

import (
    "fmt"
)

func half(number int) (int, bool) {
    if x := int(number % 2); x == 0 {
        return x, true
    } else {
        return x, false
    }
}

func main() {
    fmt.Println(half(1))
    fmt.Println(half(2))
}

我做错了什么?如何解决这个错误?

英文:

I tried to make my own code for learning how to return multiple values in main function:

package main

import "fmt"

func main() {
	fmt.Println("Enter a integer:")
	var I int
	fmt.Scanf("%d", &I)
	fmt.Println("Accepted:", I)

	O := half(I)
	fmt.Println("Returned:", O)
}

func half(N int) (int, bool) {
	var NA int
	NA = N / 2
	if NA%2 == 0 {
		fmt.Println("even")
		return NA, true
	} else {
		fmt.Println("odd")
		return NA, false
	}
}

And given error: half.go|11| multiple-value half() in single-value context.
However another variant are working:

package main

import (
	"fmt"
)

func half(number int) (int, bool) {
	if x := int(number % 2); x == 0 {
		return x, true
	} else {
		return x, false
	}
}

func main() {
	fmt.Println(half(1))
	fmt.Println(half(2))
}

What am I doing wrong? How to overcome my error?

答案1

得分: 3

如果一个函数有两个返回值,你必须要么同时“接收”它们,要么都不接收。更多信息请参考:https://stackoverflow.com/questions/28487036/return-map-like-ok-in-golang-on-normal-functions/28487270#28487270

你的 half() 函数有两个返回值,所以当使用短变量声明将返回值存储到变量中时,你必须提供两个变量:

O, even := half(I)
fmt.Println("Returned:", O, even)

在第二种情况下,你没有存储返回值,而是将它们传递给 fmt.Println(),它的签名是:

func Println(a ...interface{}) (n int, err error)

fmt.Println() 有一个可变参数,所以你可以向它传递任意数量的参数。这里发生的情况是,half() 的多个返回值作为 Println() 的可变参数的值传递进去。这是允许的,并在规范: 调用中有详细说明:

> 作为一个特例,如果函数或方法 g 的返回值的数量与另一个函数或方法 f 的参数数量相等,并且每个返回值都可以分别赋值给 f 的参数,那么调用 f(g(g的参数)) 将在绑定 g 的返回值到 f 的参数后调用 f。调用 f 除了调用 g 之外不能包含其他参数,而且 g 必须至少有一个返回值。如果 f 有一个最后的 ... 参数,它将被赋予 g 的返回值,这些返回值在分配了常规参数之后剩余。

请注意,这样做时,你不能传递/提供额外的参数,所以例如以下代码也是编译时错误

fmt.Println("Returned:", half(10))
// 错误:在单值上下文中使用多值 half()

请查看这些类似的问题:

https://stackoverflow.com/questions/28227095/go-multiple-value-in-single-value-context/28233172#28233172

https://stackoverflow.com/questions/35548073/avoid-nesting-from-conjunction-with-function-that-returns-2-values-in-go/35548183#35548183

英文:

If a function has 2 return values, you have to "expect" both of them or none at all. More on this: https://stackoverflow.com/questions/28487036/return-map-like-ok-in-golang-on-normal-functions/28487270#28487270

Your half() function has 2 return values, so when using a short variable declaration to store the returned values in variables, you have to provide 2 variables:

O, even := half(I)
fmt.Println("Returned:", O, even)

In the second case, you're not storing the returned values, you are passing them to fmt.Println() which has the signature:

func Println(a ...interface{}) (n int, err error)

fmt.Println() has a variadic parameter, so you can pass any number of arguments to it. What happens here is that all the multiple return values of half() are passed as the value of the variadic parameter of Println(). This is allowed and detailed in Spec: Calls:

> As a special case, if the return values of a function or method g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order. The call of f must contain no parameters other than the call of g, and g must have at least one return value. If f has a final ... parameter, it is assigned the return values of g that remain after assignment of regular parameters.

Note that when doing so, you are not allowed to pass / provide extra parameters, so for example the following is also a compile-time error:

fmt.Println("Returned:", half(10))
// Error: multiple-value half() in single-value context

Check out these similar questions:

https://stackoverflow.com/questions/28227095/go-multiple-value-in-single-value-context/28233172#28233172

https://stackoverflow.com/questions/35548073/avoid-nesting-from-conjunction-with-function-that-returns-2-values-in-go/35548183#35548183

答案2

得分: 1

fmt.Println接受任意数量的参数,因此接受half的结果是可以的。

在第一个例子中,你需要为两个变量提供位置。可以是:

i, b := half(2)

或者

i, _ := half(2)

如果你不需要第二个返回值。

英文:

fmt.Println accepts any number of arguments, so is ok accepting the results of half.

In the first one, you need to provide places for both variables. Either:

i,b := half(2)

or

i, _ := half(2)

if you don't need the second return.

huangapple
  • 本文由 发表于 2017年5月2日 21:53:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/43739732.html
匿名

发表评论

匿名网友

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

确定