范围拆包中的有效短变量声明

Why does this code run package main

import "fmt"

func main() {
    myMap := map[string]int{
        "a": 1,
        "b": 1,
    }
    for k, v := range myMap {
        fmt.Println(k, v)
    }
}

But this code

package main

func main() {
    x := test()
}

func test() (int, int) {
    return 0, 1
}

won't compile:

福 ~/c/p/gobook (f14d0e9)|master⚡
± : go build test.go
# command-line-arguments
./test.go:4: multiple-value test() in single-value context

Note that the same holds for arrays and slices:

package main

import "fmt"

func main() {
    myArray := [...]int{1, 2, 3}
    mySlice := myArray[:]
    for i := range mySlice {
        fmt.Println(i)
    }
    for i, x := range mySlice {
        fmt.Println(i, x)
    }
    for i := range myArray {
        fmt.Println(i)
    }
    for i, x := range myArray {
        fmt.Println(i, x)
    }
}

What is the compiler doing that allows consumers to opt-in to unpacking one or both return values in map ranges? Why did the language designers allow this for maps, slices, and arrays, but not for return values of functions?

Your program expects that you're going to accept two values returned from function test. In fact you're getting only one. To make this code work you need to make only one small change.

package main

func main() {
    x,_ := test()
}

func test() (int, int) {
    return 0, 1
}

In case of ranges apparently it has multiple interfaces. Please also pay attention to the fact that it is not a function but reserved word. It is impossible to have optional returned parameters for your function - Go doesn't support functions overloading. Unfortunately this is restricted by language (from my perspective it's a good thing that you don't create confusion and you always have only one method with only one specific name that always matches only one interface).