这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战
Switch
Go 的 switch 比 C 的更通用。 表达式不必是常量甚至整数,switch的匹配规则是从上到下进行匹配,直到找到匹配项,如果switch没有表达式,则为真。 因此,将 if-else-if-else 链编写为 switch 是可能的,并且是惯用的。
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
}
复制代码
没有自动失败?但可以以逗号分隔的列表形式呈现。
func shouldEscape(c byte) bool {
switch c {
case ' ', '?', '&', '=', '#', '+', '%':
return true
}
return false
}
复制代码
尽管它们在 Go 中不像其他一些类似 C 的语言那样常见,但 break 语句可用于提前终止 switch。 然而,有时有必要跳出周围的循环,而不是 switch,在 Go 中,这可以通过在循环上放置一个标签并“打破”该标签来实现。 这个例子展示了这两种用途。
Loop:
for n := 0; n < len(src); n += size {
switch {
case src[n] < sizeOne:
if validateOnly {
break
}
size = 1
update(src[n])
case src[n] < sizeTwo:
if n+1 >= len(src) {
err = errShortInput
break Loop
}
if validateOnly {
break
}
size = 2
update(src[n] + src[n+1]<<shift)
}
}
复制代码
当然, continue 语句也接受一个可选的标签,但它只适用于循环。
为了结束本节,这里有一个使用两个 switch 语句的字节切片比较例程:
// Compare returns an integer comparing the two byte slices,
// lexicographically.
// The result will be 0 if a == b, -1 if a < b, and +1 if a > b
func Compare(a, b []byte) int {
for i := 0; i < len(a) && i < len(b); i++ {
switch {
case a[i] > b[i]:
return 1
case a[i] < b[i]:
return -1
}
}
switch {
case len(a) > len(b):
return 1
case len(a) < len(b):
return -1
}
return 0
}
复制代码
函数(一):给返回的结果命名
可以给Go 函数的返回或结果命名并用作常规变量,就像传入参数一样。 当命名时,它们在函数开始时被初始化为它们的类型的零值; 如果函数执行不带参数的 return 语句,则结果参数的当前值将用作返回值。
这些名称不是强制性的,但它们可以使代码更短、更清晰:它们是文档。 例如下面这个例子,我们命名了函数 nextInt 的结果,很明显就能知道返回的两个 int ,哪个是哪个。
unc nextInt(b []byte, pos int) (value, nextPos int) {
}
复制代码
因为命名结果被初始化并绑定到一个简单的返回值,它们可以简化和澄清。 这是一个很好地使用它们的 io.ReadFull 版本:
func ReadFull(r Reader, buf []byte) (n int, err error) {
for len(buf) > 0 && err == nil {
var nr int
nr, err = r.Read(buf)
n += nr
buf = buf[nr:]
}
return
}
复制代码
\