Go内部培训——07.Go的控制流程

1 表达式

  • go设计简练,保留字不多。
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var

2 运算符

  • 全部运算符、分隔符,以及其他符号。
+ & += &= && == != ( )
- | -= |= || < <= [ ]
* ^ *= ^= <- > >= { }
/ << /= <<= ++ = := , ;
% >> %= >>= -- ! ... . :
&^ &^=
  • 运算符结合律全部从左到右
优先级 运算符 说明
------------+---------------------------------------------+----------------------------
high * / & << >> & &^
+ - |" ^
== != < <= < >=
<- channel
&&
low ||
  • 不支持运算符重载。尤其需要注意,"++"、"–" 是语句而非表达式。
  • 没有 “~”,取反运算也用 “^”。

3 初始化

3.1 初始化复合对象,必须使用类型标签,且左大括号必须在类型尾部。
// var a struct {x int} = {100} // syntax error
// var b []int = { 1, 2, 3} // syntax error
// c := struct {x int; y string} // syntax error: unexpected semicolon or newline
// {
// }
var a = struct{ x int }{100}
var b = []int{1, 2, 3}
3.2 初始化值以”,“分隔,可以分多行,但最后一页必须以”,“或者”}“结尾
a := []int{
    1,
    2 // Error: need trailing comma before newline in composite literal
}

a := []int{
    1,
    2, // ok
}

b := []int{
    1,
    2 } // ok

4 控制流

4.1 if语句
  • go中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“
4.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 (;;) {}
}
4.3 Range
4.3.1 类似于迭代器操作,返回 (索引, 值) 或 (键, 值)。
1st value 2nd value
------------------+-------------------+------------------+-------------------
string index s[index] unicode, rune
array/slice index s[index]
map key m[key]
channel element
4.3.2 可忽略不想要的返回值,或用 “_” 这个特殊变量。
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)
}
4.3.3 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]。
  • 建议修改成引用类型,其底层数组不会被复制。
package main

import "fmt"

func main() {
	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 // 对底层数据的修改。
		}

		fmt.Println(i, v)
	}
}
  • 另外两种引用类型 map、channel 是指针包装,而不像 slice 是 struct。
4.4 Switch
4.4.1 分支表达式可以时任意类型,不限制于常量。可省略break,默认自动终止。
x := []int{1, 2, 3}
i := 2

switch i {
    case x[1]:
        println("a")
    case 1, 3:
        println("b")
    default:
    println("c")
}
//输出
a
4.4.2 如果需要继续下一分支,可使用fallthrought,但不再判断条件。
x := 10

switch x {
    case 10:
        println("a")
        fallthrough
    case 0:
        println("b")
}
//输出
a
b
4.4.3 省略条件表达式,可当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")
}
4.4.4 Goto, Break, Continue,支持在函数内 goto 跳转。标签名区分大小写,未使用标签引发错误。
func main() {
    var i int
    for {
        fmt.Println(i)
        i++
        if i > 2 {
            goto BREAK
        }
    }

BREAK:
    fmt.Println("break")
EXIT: // Error: label EXIT defined and not used
}
4.4.5 配合标签,break 和 continue 可在多级嵌套循环中跳出。
package main

import "fmt"

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
			}
			fmt.Print(x, ":", y, " ")
		}

		fmt.Println()
	}
}
4.4.6 break 可用于 for、switch、select,而 continue 仅能用于 for 循环。
x := 100

switch {
    case x >= 0:
        if x == 0 { break }
        println(x)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值