背景
go switch 在一些场景上面的介绍。
来源
switch
Go的switch语句非常简洁。首先,您不需要在每一种情况结束时中断。
switch c {
case '&':
esc = "&"
case '\'':
esc = "'"
case '<':
esc = "<"
case '>':
esc = ">"
case '"':
esc = """
default:
panic("unrecognized escape character")
}
Not just integers 不是只有int类型
switch 作用于任何类型的值。
switch syscall.OS {
case "windows":
sd = &sysDir{
Getenv("SystemRoot") + `\system32\drivers\etc`,
[]string{
"hosts",
"networks",
"protocol",
"services",
},
}
case "plan9":
sd = &sysDir{
"/lib/ndb",
[]string{
"common",
"local",
},
}
default:
sd = &sysDir{
"/etc",
[]string{
"group",
"hosts",
"passwd",
},
}
}
Missing expression 表达式的问题
switch没有值表示“switch true”,使其成为if-else链的更简洁版本,如Effective Go的示例:
func unhex(c byte) byte {
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
case 'A' <= c && c <= 'F':
return c - 'A' + 10
}
return 0
}
Break
Go的switch语句虽然是隐式中断,但break仍然在函数中会有用:
command := ReadCommand()
argv := strings.Fields(command)
switch argv[0] {
case "echo":
fmt.Print(argv[1:]...)
case "cat":
if len(argv) <= 1 {
fmt.Println("Usage: cat <filename>")
break
}
PrintFile(argv[1])
default:
fmt.Println("Unknown command; try 'echo' or 'cat'")
}
Fall through
当满足switch的条件后想要进入后续的模块,请使用fallthrough关键字:
v := 42
switch v {
case 100:
fmt.Println(100)
fallthrough
case 42:
fmt.Println(42)
fallthrough
case 1:
fmt.Println(1)
fallthrough
default:
fmt.Println("default")
}
// Output:
// 42
// 1
// default
其他例子:
// Unpack 4 bytes into uint32 to repack into base 85 5-byte.
var v uint32
switch len(src) {
default:
v |= uint32(src[3])
fallthrough
case 3:
v |= uint32(src[2]) << 8
fallthrough
case 2:
v |= uint32(src[1]) << 16
fallthrough
case 1:
v |= uint32(src[0]) << 24
}
fallthrough 一定在代码的最后;你不能写这样的代码:
switch {
case f():
if g() {
fallthrough // Does not work!
}
h()
default:
error()
}
然而,你可以通过使用 labeled 来解决这个问题:
switch {
case f():
if g() {
goto nextCase // Works now!
}
h()
break
nextCase:
fallthrough
default:
error()
}
注意 fallthrough 在switch不生效的场景。
Multiple cases
如果想在同一情况下使用多个值,请使用逗号分隔的列表:
func letterOp(code int) bool {
switch chars[code].category {
case "Lu", "Ll", "Lt", "Lm", "Lo":
return true
}
return false
}
Type switch
通过switch 可以进行类型的判断,获取 interface{} 的类型
func typeName(v interface{}) string {
switch v.(type) {
case int:
return "int"
case string:
return "string"
default:
return "unknown"
}
}
你可以声明一个函数,它将具有处理每种类型传值的类型:
func do(v interface{}) string {
switch u := v.(type) {
case int:
return strconv.Itoa(u*2) // u has type int
case string:
mid := len(u) / 2 // split - u has type string
return u[mid:] + u[:mid] // join
}
return "unknown"
}
do(21) == "42"
do("bitrab") == "rabbit"
do(3.142) == "unknown"
Noop case 没有操作
有时不需要采取行动的情况是有用的。这个得看具体的场景和应用需要做什么事情。
func pluralEnding(n int) string {
ending := ""
switch n {
case 1:
default:
ending = "s"
}
return ending
}
fmt.Sprintf("foo%s\n", pluralEnding(1)) == "foo" //false
fmt.Sprintf("bar%s\n", pluralEnding(2)) == "bars" //false
fmt.Sprintf("foo%s", pluralEnding(1)) == "foo" //true
fmt.Sprintf("bar%s", pluralEnding(2)) == "bars" //true
//上述的\n导致字符串不一致
总结
上述介绍了switch的使用,有时候场景都是在断言的情况,判断这个值是什么类型。
以及某些数据链路上简化了if else 的使用。避免if else 过多的问题。