【问题标题】:Why isn't fallthrough allowed in a type switch?为什么在类型开关中不允许掉线?
【发布时间】:2022-04-20 02:26:35
【问题描述】:

我想知道为什么 golang 中的类型 switch 语句中不允许失败。

根据specification:“类型切换中不允许使用“fallthrough”语句。”,这并没有解释为什么不允许它。

附加的代码是为了模拟一种可能的情况,即类型 switch 语句中的失败可能有用。

注意!此代码不起作用,它会产生错误:“cannot fallthrough in type switch”。我只是想知道在类型切换中不允许使用 fallthrough 语句的可能原因是什么。

//A type switch question
package main

import "fmt"

//Why isn't fallthrough in type switch allowed?
func main() {
    //Empty interface
    var x interface{}

    x = //A int, float64, bool or string value

    switch i := x.(type) {
    case int:
        fmt.Println(i + 1)
    case float64:
        fmt.Println(i + 2.0)
    case bool:
        fallthrough
    case string:
        fmt.Printf("%v", i)
    default:
        fmt.Println("Unknown type. Sorry!")
    }
}

【问题讨论】:

    标签: switch-statement go


    【解决方案1】:

    您希望fallthrough 如何工作?在此类型切换中,i 变量的类型取决于调用的特定情况。所以在case bool 中,i 变量的类型为bool。但在case string 中,它的类型为string。所以要么你要求i 神奇地改变它的类型,这是不可能的,要么你要求它被一个新变量i string 遮蔽,因为它的值来自x 实际上不是 string


    这是一个尝试说明问题的示例:

    switch i := x.(type) {
    case int:
        // i is an int
        fmt.Printf("%T\n", i); // prints "int"
    case bool:
        // i is a bool
        fmt.Printf("%T\n", i); // prints "bool"
        fallthrough
    case string:
        fmt.Printf("%T\n", i);
        // What does that type? It should type "string", but if
        // the type was bool and we hit the fallthrough, what would it do then?
    }
    

    唯一可能的解决方案是让fallthrough 导致后续的case 表达式将i 保留为interface{},但这将是一个令人困惑和错误的定义。

    如果您确实需要这种行为,您已经可以使用现有功能完成此操作:

    switch i := x.(type) {
    case bool, string:
        if b, ok := i.(bool); ok {
            // b is a bool
        }
        // i is an interface{} that contains either a bool or a string
    }
    

    【讨论】:

    • 感谢您的解释,但我必须承认我真的不明白为什么 fmt.Printf("%T\n", i) 不会再次打印“bool”。因为在常规的失败中,case 语句被忽略并且表达式是类型无意识的。这可能是因为我将它与一个常规的 switch 语句联系在一起,我很难弄清楚这一点。
    • @Mandarin:如果istring 则编译的代码如果ibool 则可能无法编译。您不能编写将一个变量视为具有两种不同类型的代码。那么icase bool 中有什么类型呢?它当然不可能是bool,如果是string,那么你必须丢弃icase bool 中的值,如果没有该值,你的代码将毫无用处。
    • 实际上,如果i 始终是interface{},它可以工作,因此case bool, string: /* i is an interface{} pointing to either bool or string */ 可以与case bool: fallthrough; case string: /* i is an interface{} pointing to either bool or string */ 相同
    • @Zippoxer:除非我说过这会非常令人困惑,而且它不是定义语言的非常有用的方式。仅仅因为技术上可以完成的事情并不意味着它是一个好主意。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 2016-09-21
    • 2019-08-06
    • 1970-01-01
    相关资源
    最近更新 更多