Effective Go: 控制结构(二)

这是我参与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
}
复制代码

\

猜你喜欢

转载自juejin.im/post/7032610522671349790
今日推荐