Effective Go:控制结构(二)

158 阅读2分钟

这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战

For

Go 的for 循环与 C 的相似但不相同。它统一了 for 和 while,没有 do-while。共有三种形式,其中只有一种带有分号。

// Like a C for
for init; condition; post { }
​
// Like a C while
for condition { }
​
// Like a C for(;;)
for { }

简短的声明使得在循环中声明索引变量变得容易。

sum := 0
for i := 0; i < 10; i++ {
    sum += i
}

如果您在数组、切片、字符串或映射上循环,或从通道读取,range子句可以管理循环。

for key, value := range oldMap {
    newMap[key] = value
}

如果您只需要范围中的第一项(键或索引),请删除第二项:

for key := range m {
    if key.expired() {
        delete(m, key)
    }
}

如果您只需要范围中的第二项(值),请使用空白标识符(下划线)来丢弃第一项:

sum := 0
for _, value := range array {
    sum += value
}

空白标识符有很多用途,如后面的部分所述

对于字符串,range表达式可以做更多的工作,通过解析 UTF-8 来分解单个 Unicode 字符串 (rune 是 Go 中单个 Unicode 代码点的术语。有关详细信息,请参阅语言规范。)

for pos, char := range "日本\x80語" { // \x80 is an illegal UTF-8 encoding
    fmt.Printf("character %#U starts at byte position %d\n", char, pos)
}

打印结果

character U+65E5 '日' starts at byte position 0
character U+672C '本' starts at byte position 3
character U+FFFD '�' starts at byte position 6
character U+8A9E '語' starts at byte position 7

最后,Go 没有逗号运算符,++ 和 -- 是语句而不是表达式。因此,如果你想在一个 for 中运行多个变量,你应该使用并行赋值

// Reverse a
for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
    a[i], a[j] = a[j], a[i]
}

类型转化

Switch还可用于判断变量类型。 这种使用类型断言的语法,括号内是关键字类型。 如果 switch 在表达式中声明了一个变量,则该变量将在每个子句中具有相应的类型。 在这种情况下重用名称也是惯用的,实际上在每种情况下都声明了一个具有相同名称但类型不同的新变量。

var t interface{}
t = functionOfSomeType()
switch t := t.(type) {
default:
    fmt.Printf("unexpected type %T\n", t)     // %T prints whatever type t has
case bool:
    fmt.Printf("boolean %t\n", t)             // t has type bool
case int:
    fmt.Printf("integer %d\n", t)             // t has type int
case *bool:
    fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
case *int:
    fmt.Printf("pointer to integer %d\n", *t) // t has type *int
}

\