第2章 表达式

2.1保留字

breakdefaultfuncinterfaceselect
casedefergomapstruct
chanelsegotopackageswitch
constfallthroughifrangetype
continueforimportreturnvar

2.2运算符

位运算演示

fmt.Printf("0110 & 1011 = %v (0010) \n", (0110 & 1011))   // AND 都为 1
fmt.Printf("0110 | 1011 = %v (1111) \n", (0110 | 1011))   // OR 至少一个为 1
fmt.Printf("0110 ^ 1011 = %v (1101) \n", (0110 ^ 1011))   // XOR 只能一个为 1
fmt.Printf("0110 &^ 1011 = %v (0100) \n", (0110 &^ 1011)) // AND NOT 清除标志位

标志位操作

a := 0
a |= 1 << 2         // 0000100:在bit2设置标志位
a |= 1 << 6         // 1000100:在bit6设置标志位
a = a &^ (1 << 6)   // 0000100:清除bit6标志位

不支持运算符重载,尤其需要注意,“++”、“–”是语句而非表达式

n:=0
p:=&n

b := n++        //syntax error: unexpected ++ at end of statement
if n++ == 1{}   //syntax error: unexpected ==, expecting  
++n             //syntax error: unexpected ++, expecting 

n++
*p++            //(*p)++

没有“~”,取反运算也用“^”

var x uint8 = 1
fmt.Printf("变量x=%08b\n", x)
fmt.Printf("变量^x=%08b\n", ^x)

2.3初始化

初始化复合对象,必须使用类型标签,且左大括号必须在类型尾部

var a = struct{ x int }{100}
var b = []int{1, 2, 3}

初始化值以“,”分隔,可以分多行,但最后一行必须以“,”或“}”结尾

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

b := []int{
	1,
	2}

2.4控制流

IF
可省略条件表达式括号
支持初始化语句,可定义代码块局部变量
代码块左大括号必须在条件表达式尾部
不支持三元操作符“a > b ? a : b”

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])
}

FOR
支持三种循环方式,包括while语法

s := "abc"

//第一种
for i, n := 0, len(s); i < n; i++ { //常见的for循环,支持初始化语句
	fmt.Println(s[i])
}

//第二种
n := len(s)
for n > 0 {                 //替代while(n>0){}
       fmt.Println(s[n])       //替代for(;n>0;){}
       n--
}

//第三种
for {                       //替代while(true){}
    fmt.Println(s)          //替代for(;;){}
}

Range
类似迭代器操作,返回(索引,值)或(键,值),可忽略不想要的返回值,或用“_”这个特殊变量,有四种用法

s := "abc"

//第一种
for i := range s { // 忽略 2nd value,⽀持 string/array/slice/map。
	fmt.Println(s[i])
}

// 第二种
for _, c := range s { // 忽略 index。
	fmt.Println(c)
}

// 第三种
for range s { // 忽略全部返回值,仅迭代。
	fmt.Println("忽略全部返回值,仅迭代")
}

// 第四种
m := map[string]int{"a": 1, "b": 2}
for k, v := range m { // 返回 (key, value)。
	fmt.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.Printf("确认修改有效,输出%v \n", a) // 确认修改有效,输出 [0, 999, 999]
	}
	a[i] = v + 100 // 使⽤复制品中取出的 value 修改原数组
}
fmt.Printf("使⽤复制品中取出的 value 修改原数组 %v \n", a) // 输出 [100, 101, 102]

建议改用引用类型,其底层数据不会被复制
另外两种引⽤类型 map、channel 是指针包装,⽽不像 slice 是 struct

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

Switch
分支表达式可以是任意类型,不限于常量。可省略 break,默认自动终止

x := []int{1, 2, 3}
i := 2
switch i {
case x[1]:
	println("a")
case 1, 3:
	println("b")
default:
	println("c")
}

如需要继续下⼀分⽀,可使⽤ fallthrough,但不再判断条件

x := 10
switch x {
case 10:
	println("a")
	fallthrough
case 0:
	println("b")
}

省略条件表达式,可当 if…else if…else 使用

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

//第一种
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")
}

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
}
/*
	0
	1
	2
	break
*/

配合标签,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
			}
			fmt.Print(x, ":", y, " ")
		}
		fmt.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
	}
	fmt.Println(x)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值