兄弟連go教程(10)表示式 - 控制流

尹成發表於2018-07-04
1. IF
很特別的寫法:
•可省略條件表示式括號。
•⽀支援初始化語句,可定義程式碼塊區域性變數。
•程式碼塊左⼤大括號必須在條件表示式尾部。
x := 0
// if x > 10 // Error: missing condition in if statement
// {
// }
if n := "abc"; x > 0 { // 初始化語句未必就是定義變數,⽐比如 println("init") 也是可以的。
println(n[2])
} else if x < 0 { // 注意 else if 和 else 左⼤大括號位置。
println(n[1])
} else {
println(n[0])
}

不⽀支援三元操作符 "a > b ? a : b"。

2. For

⽀支援三種迴圈⽅方式,包括類 while 語法。

s := "abc"

for i, n := 0, len(s); i < n; i++ { // 常⻅見的 for 迴圈,⽀支援初始化語句。

println(s[i])

}

n := len(s)

for n > 0 { // 替代 while (n > 0) {}

println(s[n]) // 替代 for (; n > 0;) {}

n--

}

for { // 替代 while (true) {}

println(s) // 替代 for (;;) {}

}

不要期望編譯器能理解你的想法,在初始化語句中計算出全部結果是個好主意。

func length(s string) int {

println("call length.")

return len(s)

}

func main() {

s := "abcd"

for i, n := 0, length(s); i < n; i++ { // 避免多次調⽤用 length 函式。

println(i, s[i])

}

}

輸出:

call length.

0 97

1 98

2 99

3 100
3. Range
類似迭代器操作,返回 (索引, 值) 或 (鍵, 值)。

1st value 2nd value
------------------+-------------------+------------------+-------------------
string index s[index] unicode, rune
array/slice index s[index]
map key m[key]
channel element

可忽略不想要的返回值,或⽤用 "_" 這個特殊變數。
s := "abc"
for i := range s { // 忽略 2nd value,⽀支援 string/array/slice/map。
println(s[i])
}
for _, c := range s { // 忽略 index。
println(c)
}
for range s { // 忽略全部返回值,僅迭代。
...
}
m := map[string]int{"a": 1, "b": 2}
for k, v := range m { // 返回 (key, value)。
println(k, v)
}

注意,range 會複製物件。
a := [3]int{0, 1, 2}
for i, v := range a { // index、value 都是從複製品中取出。
if i == 0 { // 在修改前,我們先修改原陣列。
a[1], a[2] = 999, 999
fmt.Println(a) // 確認修改有效,輸出 [0, 999, 999]。
}
a[i] = v + 100 // 使⽤用複製品中取出的 value 修改原陣列。
}
fmt.Println(a) // 輸出 [100, 101, 102]。


建議改⽤用引⽤用型別,其底層資料不會被複制。
s := []int{1, 2, 3, 4, 5}
for i, v := range s { // 複製 struct slice { pointer, len, cap }。
if i == 0 {
s = s[:3] // 對 slice 的修改,不會影響 range。
s[2] = 100 // 對底層資料的修改。
}
println(i, v)
}

輸出:

0 1
1 2
2 100
3 4
4 5

另外兩種引⽤用型別 map、channel 是指標包裝,⽽而不像 slice 是 struct。

4. Switch

分⽀支表示式可以是任意型別,不限於常量。可省略 break,預設⾃自動終⽌止。

x := []int{1, 2, 3}

i := 2

switch i {

case x[1]:

println("a")

case 1, 3:

println("b")

default:

println("c")

}

輸出:

a

如需要繼續下⼀一分⽀支,可使⽤用 fallthrough,但不再判斷條件。

x := 10



switch x {

case 10:

println("a")

fallthrough

case 0:

println("b")

}

輸出:

a

b

省略條件表示式,可當 if...else if...else 使⽤用。

switch {

case x[1] > 0:

println("a")

case x[1] < 0:

println("b")

default:

println("c")

}

switch i := x[2]; { // 帶初始化語句

case i > 0:

println("a")

case i < 0:

println("b")

default:

println("c")

}

5.Goto, Break, Continue
⽀支援在函式內 goto 跳轉。標籤名區分⼤大⼩小寫,未使⽤用標籤引發錯誤。
func main() {
var i int
for {
println(i)
i++
if i > 2 { goto BREAK }
}

BREAK:
println("break")
EXIT: // Error: label EXIT defined and not used
}

配合標籤,break 和 continue 可在多級巢狀迴圈中跳出。
func main() {
L1:
for x := 0; x < 3; x++ {
L2:
for y := 0; y < 5; y++ {
if y > 2 { continue L2 }
if x > 1 { break L1 }
print(x, ":", y, " ")
}
println()
}
}

輸出:
0:0 0:1 0:2
1:0 1:1 1:2

附:break 可⽤用於 for、switch、select,⽽而 continue 僅能⽤用於 for 迴圈。
x := 100
switch {
case x >= 0:
if x == 0 { break }
println(x)
}

尹成老師

QQ77025077 

微信18510341407

所有視訊在尹成學院

www.yinchengxueyuan.com

尹成百度雲請聯絡QQ475318423



相關文章