语法 1 2 3 4 5 6 7 8 9 10 switch initStmt; expr { case expr1: case expr2_1, expr2_2: case exprN: default : }
顺序
按照定义顺序(从上到下,从左到右),先到先得
,匹配后中断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 package mainfunc case1 () int { println ("eval case1" ) return 1 } func case2_1 () int { println ("eval case2_1" ) return 0 } func case2_2 () int { println ("eval case2_2" ) return 2 } func case3 () int { println ("eval case3" ) return 3 } func switchexpr () int { println ("eval switchexpr" ) return 2 } func main () { switch switchexpr() { case case1(): println ("exec case1" ) default : println ("exec default" ) case case2_2(), case2_1(): println ("exec case2" ) case case3(): println ("exec case3" ) } }
将匹配成功率高
的 case 排在前面
(上/左),有助于提升 switch 语句的执行效率
创新
C
switch 语句对表达式类型
有限制,只能是 int
或者枚举
类型
每个 case
语句只可以有一个表达式
除非显式使用 break
跳出,程序默认总是执行下一个
case 语句
类型
只要类型支持比较
操作,都可以作为 switch 语句中的表达式类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package maintype person struct { name string age int } func main () { p := person{name: "John" , age: 20 } switch p { case person{name: "John" , age: 20 }: println ("John 20" ) case person{name: "John" , age: 30 }: println ("John 30" ) case person{name: "John" , age: 40 }: println ("John 40" ) default : println ("No match" ) } }
当 switch 表达式的类型为布尔类型
时,且求值结果始终
为 true
时,可以省略
switch 后面的表达式
1 2 3 4 5 6 7 8 switch a, b, c := 1 , 2 , 3 ; true {case true : println ("true" , a) case false : println ("false" , b) default : println ("default" , c) }
1 2 3 4 5 6 7 8 switch a, b, c := 1 , 2 , 3 ; { case true : println ("true" , a) case false : println ("false" , b) default : println ("default" , c) }
1 2 3 4 5 6 7 8 switch { case true : println ("true" ) case false : println ("false" ) default : println ("default" ) }
临时变量
与 if 和 for 一样,switch 支持 initStmt 来声明
只在这个 switch 隐式代码块中使用的变量
1 2 3 4 5 6 switch a, b, c := 1 , 2 , 3 ; a + b + c {case 6 : fmt.Printf("%d+%d+%d = %d\n" , a, b, c, a+b+c) default : println ("default" ) }
表达式列表
case 语句支持表达式列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void check_work_day (int a) { switch (a) { case 1 : case 2 : case 3 : case 4 : case 5 : printf ("Work day\n" ); break ; case 6 : case 7 : printf ("Weekend\n" ); break ; default : printf ("Invalid day\n" ); } }
1 2 3 4 5 6 7 8 9 10 func check_work_day (a int ) { switch a { case 1 , 2 , 3 , 4 , 5 : fmt.Println("work day" ) case 6 , 7 : fmt.Println("weekend" ) default : fmt.Println("invalid day" ) } }
fallthrough
取消默认执行下一个 case 的代码逻辑的语义,除非显式使用 fallthrough
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package mainfunc case1 () int { println ("eval case1" ) return 1 } func case2 () int { println ("eval case2" ) return 2 } func switchexpr () int { println ("eval switchexpr" ) return 1 } func main () { switch switchexpr() { case case1(): println ("exec case1" ) fallthrough case case2(): println ("exec case2" ) fallthrough default : println ("exec default" ) } }
fallthrough 会跳过
下一个 case 表达式的求值
,而是直接进入
对应分支
type switch
switch 语句支持求值结果为类型信息
的表达式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 var x interface {} = 13 switch x.(type ) { case nil : println ("nil" ) case int : println ("int" ) case float64 : println ("float64" ) case string : println ("string" ) case bool : println ("bool" ) default : println ("unknown" ) }
x.(type)
为 switch 语句专有
的,其中 x
必须为接口类型变量
,求值结果为对应的动态类型
1 2 3 4 5 6 switch v := x.(type ) { case nil , int , float64 , string , bool : fmt.Printf("%T, %v\n" , v, v) default : fmt.Printf("%v\n" , v) }
Go 中所有类型
都实现了 interface{}
类型
接口类型变量
才能使用 type switch
,并且所有 case 语句中的类型必须实现
switch 关键字后面变量的接口类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package maintype Human interface { Run() } type Man struct {} func (m Man) Run() {} func main () { var man Man var human Human = man switch human.(type ) { case Man: println ("man" ) default : println ("default" ) } }
break
不带 label
的 break 中断执行并跳出的,是同一函数内 break 语句所在的最内层
的 for
、switch
、select
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainfunc main () { sl := []int {5 , 19 , 6 , 3 , 8 , 12 } firstEven := -1 for _, v := range sl { switch v % 2 { case 0 : firstEven = v break case 1 : } } println (firstEven) }
label
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package mainfunc main () { sl := []int {5 , 19 , 6 , 3 , 8 , 12 } firstEven := -1 loop: for _, v := range sl { switch v % 2 { case 0 : firstEven = v break loop case 1 : } } println (firstEven) }