流程控制

if条件语句

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

条件赋值(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

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

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

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
  2. struct User {
  3. name string
  4. age int
  5. }
  6. pub fn (m &User) str() string {
  7. return 'name:$m.name,age:$m.age'
  8. }
  9. type MySum = User | int | string //联合类型声明
  10. pub fn (ms MySum) str() string {
  11. match ms { //如果函数的参数或者接收者是联合类型,可以使用match进一步判断类型
  12. int {
  13. return ms.str()
  14. }
  15. string {
  16. return ms // ms的类型是string
  17. }
  18. User {
  19. return ms.str() // ms的类型是User
  20. }
  21. // else { //如果之前的分支已经穷尽了所有可能,else语句不需要,如果没有穷尽所有可能,则else语句是必须的
  22. // return 'unknown'
  23. // }
  24. }
  25. }

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

for is语句

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

  1. module main
  2. struct Milk {
  3. mut:
  4. name string
  5. }
  6. struct Eggs {
  7. mut:
  8. name string
  9. }
  10. type Food = Eggs | Milk
  11. fn main() {
  12. mut f := Food(Eggs{'test'})
  13. //不带mut
  14. for f is Eggs {
  15. println(typeof(f).name)
  16. break
  17. }
  18. //等价于
  19. for {
  20. if f is Eggs {
  21. println(typeof(f).name)
  22. break
  23. }
  24. }
  25. //带mut
  26. for mut f is Eggs {
  27. f.name = 'eggs'
  28. println(f.name)
  29. break
  30. }
  31. //等价于
  32. for {
  33. if mut f is Eggs {
  34. f.name = 'eggs'
  35. println(f.name)
  36. break
  37. }
  38. }
  39. }

for循环结合or代码块

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

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. }
  21. fn do_send(ch1 chan int, ch2 chan f64) {
  22. ch1 <- 3
  23. ch2 <- 5.0
  24. ch2.close()
  25. ch1 <- 2
  26. ch1.close()
  27. }

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. }