流程控制

if条件语句

1. module main

3. fn main() {
4. a := 10
5. b := 20
6. if a < b {
7. println('$a < $b')
8. } else if a > b {
9. println('$a > $b')
10. } else {
11. println('$a == $b')
12. }
13. }

条件赋值(if表达式)

1. num := 777
2. // 简单的条件赋值
3. s := if num % 2 == 0 { 'even' } else { 'odd' }
4. println(s)
5. // "odd"
6. // 多条件赋值
7. a, b, c := if true { 1, 'awesome', 13 } else { 0, 'bad', 0 }
8. println(a)
9. println(b)
10. println(c)

likely/unlikely

likely和unlikely这两个内置函数实现的是跟C的likely一样的效果,可以实现给条件分支的性能做优化,一般的代码来说,使用的场景不多

1. module main

3. fn main() {
4. x := 1
5. if _likely_(x == 1) { //告诉编译器,大部分情况的分支是这个,做代码优化
6. println('a')
7. } else {
8. println('b')
9. }
10. if _unlikely_(x == 1) { //告诉编译器,大部分情况的分支不是这个,做代码优化
11. println('a')
12. } else {
13. println('b')
14. }
15. }

match分支语句

match要求穷尽所有可能,所以基本都要带上else语句

1. fn main() {
2. os := 'macos'
3. match os {
4. 'windows' { println('windows') }
5. 'linux' { println('linux') }
6. 'macos' { println('macos') }
7. else { println('unknow') }
8. }
9. }

匹配的值也可以多个,用逗号分隔:

1. fn main() {
2. os := 'macos'
3. match os {
4. 'windows' { println('windows') }
5. 'macos', 'linux' { println('macos or linux') }
6. else { println('unknow') }
7. }
8. }

match赋值(match表达式)

1. os := 'macos'
2. price := match os {
3. 'windows' { 100 }
4. 'linux' { 120 }
5. 'macos' { 150 }
6. else { 0 }
7. }
8. println(price)
9. //输出150
10. //多变量match赋值
11. a, b, c := match false {
12. true { 1, 2, 3 }
13. false { 4, 5, 6 }
14. else { 7, 8, 9 }
15. }
16. println(a)
17. println(b)
18. println(c)

match的同时,加上mut ,可以修改匹配变量,通常是配合for in 语句结合使用

1. //参考代码
2. for stmt in file.stmts {
3. match mut stmt {
4. ast.ConstDecl {
5. c.stmt(*it)
6. }
7. else {}
8. }
9. }

使用match判断联合类型的具体类型

1. module main

3. struct User {
4. name string
5. age  int
6. }

8. pub fn (m &User) str() string {
9. return 'name:$m.name,age:$m.age'
10. }

12. type MySum = User | int | string //联合类型声明

14. pub fn (ms MySum) str() string {
15. match ms { //如果函数的参数或者接收者是联合类型,可以使用match进一步判断类型
16. int {
17. return ms.str()
18. }
19. string {
20. return ms // ms的类型是string
21. }
22. User {
23. return ms.str() // ms的类型是User
24. }
25. // else { //如果之前的分支已经穷尽了所有可能,else语句不需要,如果没有穷尽所有可能,则else语句是必须的
26. //     return 'unknown'
27. // }
28. }
29. }

for 循环语句

for的四种形式:

  1. 传统的:for i=0;i<100;i++ {}
1. for i := 0; i < 10; i++ {
2. // 跳过6
3. if i == 6 {
4. continue
5. }
6. println(i)
7. }

为了简洁的目的,for里面的i默认就是mut可变的,不需要特别声明为mut,如果声明了编译器会报错

  1. 替代while:for i<100 {}
1. mut sum := 0
2. mut i := 0
3. for i <= 100 {
4. sum += i
5. i++
6. }
7. println(sum)
8. // 输出"5050"
  1. 无限循环:for {}
1. mut num := 0
2. for {
3. num++
4. if num >= 10 {
5. break
6. }
7. }
8. println(num)
9. // "10"
  1. 遍历:for i in xxx {}

for in可以用来遍历字符串,数组,区间,字典这四种类型

遍历字符串:

1. str := 'abcdef'
2. // 遍历value
3. for s in str {
4. println(s.str())
5. }
6. // 遍历index和value
7. for i, s in str {
8. println('index:$i,value:$s.str()')
9. }

遍历数组:

1. numbers := [1, 2, 3, 4, 5]
2. for num in numbers {
3. println('num:$num')
4. }
5. for i, num in numbers {
6. println('i:$i,num:$num')
7. }
8. // 或者这种区间的写法也可以
9. for i in 0 .. numbers.len {
10. println('num:${numbers[i]}')
11. }

遍历区间:

1. mut sum := 0
2. for i in 1 .. 11 { // 左闭右开,遍历区间
3. sum += i
4. }
5. println(sum)    // 55

遍历字典:

1. m := {
2. 'name': 'jack'
3. 'age':  '20'
4. 'desc': 'good man'
5. }
6. for key, value in m {
7. println('key:$key,value:$value')
8. }

跟其他语言一样continue用来重新继续当前循环,break用来跳出当前循环

如果存在多层嵌套的循环,也可以使用continue label和break label来控制重新/跳出标签那一层的循环

1. fn main() {
2. mut i := 4
3. goto L1
4. L1: for { //在for前加标签
5. i++
6. for {
7. if i < 7 {continue L1} //从顶层循环继续
8. else {break L1} //直接跳出顶层循环
9. }
10. }
11. println(i)

13. goto L2
14. L2: for  ;; i++ {
15. for {
16. if i < 17 {continue L2}
17. else {break L2}
18. }
19. }
20. println(i)
21. goto L3
22. L3: for e in [1,2,3,4] {
23. i = e
24. for {
25. if i < 3 {continue L3}
26. else {break L3}
27. }
28. }
29. println(i)
30. }

for is语句

用于联合类型的类型循环判断(感觉没啥用,就是一个语法糖而已)

1. module main

3. struct Milk {
4. mut:
5. name string
6. }

8. struct Eggs {
9. mut:
10. name string
11. }

13. type Food = Eggs | Milk

15. fn main() {
16. mut f := Food(Eggs{'test'})
17. //不带mut
18. for f is Eggs {
19. println(typeof(f).name)
20. break
21. }
22. //等价于
23. for {
24. if f is Eggs {
25. println(typeof(f).name)
26. break
27. }
28. }
29. //带mut
30. for mut f is Eggs {
31. f.name = 'eggs'
32. println(f.name)
33. break
34. }
35. //等价于
36. for {
37. if mut f is Eggs {
38. f.name = 'eggs'
39. println(f.name)
40. break
41. }
42. }
43. }

for循环结合or代码块

1. module main

3. import os

5. fn main() {
6. //for循环结合or代码块,更简洁一些
7. for line in os.read_lines(@FILE) or { panic('文件不存在') } {
8. // 报错
9. // for line in os.read_lines('不存在的文件') or { panic('文件不存在') } {
10. println(line)
11. }

for select语句

for select语句主要在并发中使用,用来循环监听多个chanel,更多内容可以参考并发章节

1. fn main() {
2. ch1 := chan int{}
3. ch2 := chan f64{}
4. go do_send(ch1, ch2)
5. mut a := 0
6. mut b := 0
7. for select { // 循环监听channel的写入,写入后执行for代码块,直到所有监听的channel都已关闭
8. x := <-ch1 {
9. a += x
10. }
11. y := <-ch2 {
12. a += int(y)
13. }
14. } { // for代码块
15. b++ // 写入3次
16. println('${b}. event')
17. }
18. println(a)
19. println(b)
20. }

22. fn do_send(ch1 chan int, ch2 chan f64) {
23. ch1 <- 3
24. ch2 <- 5.0
25. ch2.close()
26. ch1 <- 2
27. ch1.close()
28. }

goto语句

goto语句只能在函数内部跳转

1. fn main() {
2. mut i := 0
3. a: //定义跳转标签
4. i++
5. // a: i++ //标签和语句在同一行也可以正常运行
6. if i < 3 {
7. goto a //跳转到a标签
8. }
9. println(i)
10. }