为什么在 Go 类型开关中声明一个单独的变量?

Why is a separate variable declared in a Go type switch?

我无法理解为什么类型开关是用 switch 语句中定义的附加变量编写的。下面的代码似乎是被认可的做事方式:

func test_func(i interface{}) {
    switch v := i.(type) {
    case int:
        fmt.Printf("%T\n", v)
    case float64:
        fmt.Printf("%T\n", v)
    case int:
        fmt.Printf("I don't know about type %T!\n", v)
    }
}

func main() {
    test_func(float64(34))
    test_func(int(34))
    test_func("hello world")
}

不出所料,这个 returns:

float64
int
I don't know about type string!

但是,我可以稍微更改 test_func,这样 v 就不会在 switch 语句中定义,而是在我们的 case 语句中使用 i

func test_func(i interface{}) {
    switch i.(type) {
    case int:
        fmt.Printf("%T\n", i)
    case float64:
        fmt.Printf("%T\n", i)
    case int:
        fmt.Printf("I don't know about type %T!\n", i)
    }
}

func main() {
    test_func(float64(34))
    test_func(int(34))
    test_func("hello world")
}

并且输出没有改变。这两种形式似乎可以互换。当我可以使用 i 时,为什么还要麻烦定义 v?后一种情况更简单,因为需要跟踪的变量更少;也许它的性能更高。

它们不可互换;您只是将 i 传递给一个可以接受它的函数,而不管其类型如何(fmt.Printf 格式字符串后的参数是 interface{} 类型)。 i仍然是它原来的类型,因为一个变量的类型不能改变

如果你真的想根据它的类型对它做些什么,你需要第一种形式,这样 v 就是 case 语句中的类型。无论您是否将键入的值分配给变量,原始变量 i 都会保留其原始类型。

这在 Tour of Go: Type switches

中有很好的介绍