Go语言运算符&流程控制&数组

1 Go语言运算符

1.1 算数运算符

a := 30 b := 20

运算符描述实例
+a + b = 50
-减号a - b = 10
*a * b = 600
/除(求商)a / b = 1
%除(求余)a % b = 10

注意 ++--在Go语言中为单独的语句,不是运算符。

1.2 关系运算符

运算符描述
==检查两个值是否相等,如果相等返回 True 否则返回 False。
!=检查两个值是否不相等,如果不相等返回 True 否则返回 False。
>检查左边值是否大于右边值,如果是返回 True 否则返回 False。
>=检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。
<检查左边值是否小于右边值,如果是返回 True 否则返回 False。
<=检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。

1.3 逻辑运算符

运算符描述
&&逻辑 AND 运算符。 如果两边的操作数都是 True,则为 True,否则为 False。
II逻辑 OR 运算符。 如果两边的操作数有一个 True,则为 True,否则为 False。
!逻辑 NOT 运算符。 如果条件为 True,则为 False,否则为 True。

1.4 位运算符

位运算符对整数在内存中的二进制位进行操作。

运算符描述
&参与运算的两数各对应的二进位相与。(两位均为1才为1)
I参与运算的两数各对应的二进位相或。(两位有一个为1就为1)
^参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。
<<左移n位就是乘以2的n次方。“a<<b”是把a的各二进位全部左移b位,高位丢弃,低位补0。
>>右移n位就是除以2的n次方。“a>>b”是把a的各二进位全部右移b位。

1.5 赋值运算符

运算符描述
=简单的赋值运算符,将一个表达式的值赋给左值
+=相加后再赋值
-=相减后再赋值
*=相乘后再赋值
/=相除后再赋值
%=求余后再赋值
<<=左移后赋值
>>=右移后赋值
&=按位与后赋值
I=按位或后赋值
^=按位异或后赋值

2 Go语言流程控制

Go语言提供了条件分支 if,状态分支switch,循环 for,跳转 goto,延迟执行 defer,这些流程控制语句。

2.1 if else 条件分支结构

依据条件是否满足确定执行哪个分支。

if 表达式1 {
    分支1
} else if 表达式2 {
    分支2
} else{
    分支3
}

当表达式1的结果为true时,执行分支1,否则判断表达式2,如果满足则执行分支2,都不满足时,则执行分支3。if判断中的else ifelse都是可选的,可以根据实际需要进行选择。

Go语言规定与if匹配的左括号{必须与if和表达式放在同一行}放在其他位置会触发编译错误。 同理,与else匹配的{也必须与else写在同一行},else也必须与上一个ifelse if右边的大括号在同一行。

score := 85
	if score >= 90 {
		fmt.Println("优秀")
	} else if score > 80 {
		fmt.Println("良好")
	} else if score > 60{
		fmt.Println("及格")
	}else {
		fmt.Println("不及格")
	}

思考:上面这种if条件判断和下面这种条件判断区别是什么?


	if score := 85; score >= 90 {
		fmt.Println("优秀")
	} else if score > 80 {
		fmt.Println("良好")
	} else if score > 60{
		fmt.Println("及格")
	}else {
		fmt.Println("不及格")
	}
	//作用域

2.2 for 循环结构

Go语言中没有while循环,所有循环类型均可以使用for关键字来完成。

for 初始语句;条件表达式;结束语句{
    循环体语句
}

条件表达式返回true时循环体不停地进行循环,直到条件表达式返回false时自动退出循环。

func main() {
	for i := 0; i < 10; i++ {
		fmt.Print(i) //打印 0-9
	}
}

for循环的初始语句可以被忽略,但是初始语句后的分号必须要写,例如:

func main() {
	i := 0
	for ; i < 10; i++ {
		fmt.Print(i)
	}
}

for循环的初始语句和结束语句都可以省略,例如:

func main() {
	i := 0
	for i < 10 {
		fmt.Print(i)
		i++
	}
}

这种写法类似于其他编程语言中的while,在while后添加一个条件表达式,满足条件表达式时持续循环,否则结束循环。

无限循环
for {
    循环体语句
}

for循环可以通过breakgotoreturnpanic语句强制退出循环。

2.3 for range 键值循环

Go语言中可以使用for range遍历数组、切片、字符串、map及通道(channel)。 通过for range遍历的返回值有以下规律:

  1. 数组、切片、字符串返回索引和值。
  2. map返回键和值。
  3. 通道(channel)只返回通道内的值。
switch case

使用switch语句可方便地对大量的值进行条件判断。

func main() {
	finger := 3
	switch finger {
	case 1:
		fmt.Print("大拇指")
	case 2:
		fmt.Printl("食指")
	case 3:
		fmt.Print("中指")
	case 4:
		fmt.Print("无名指")
	case 5:
		fmt.Print("小拇指")
	default:
		fmt.Print("无效的输入!")
	}
}

Go语言规定每个switch只能有一个default分支。

一个分支可以有多个值,多个case值中间使用英文逗号分隔。

func main() {
	switch n := 7; n {
	case 1, 3, 5, 7, 9:
		fmt.Println("奇数")
	case 2, 4, 6, 8:
		fmt.Println("偶数")
	default:
		fmt.Println(n)
	}
}

分支还可以使用表达式,这时候switch语句后面不需要再跟判断变量,例如:

func main() {
	age := 30
	switch {
	case age < 25:
		fmt.Println("年轻")
	case age > 25 && age < 35:
		fmt.Println("快老了")
	case age > 60:
		fmt.Println("广场舞")
	default:
		fmt.Println("25岁||35岁||60岁")
	}
}

fallthrough语法可以执行满足条件的case的下一个case,是为了兼容C语言中的case设计的。

func main() {
	s := "a"
	switch {
	case s == "a":
		fmt.Println("a")
		fallthrough
	case s == "b":
		fmt.Println("b")
	case s == "c":
		fmt.Println("c")
	default:
		fmt.Println("...")
	}
}

输出

a
b

goto 跳转

goto语句通过标签进行代码间的无条件跳转。goto语句可以在快速跳出循环、避免重复退出上有一定的帮助。Go语言中使用goto语句能简化一些代码的实现过程。 例如双层嵌套的for循环要退出时:

func main() {
	var breakFlag bool
	for i := 0; i < 10; i++ {
		for j := 0; j < 10; j++ {
			if j == 2 {
				// 设置退出标签
				breakFlag = true
				break
			}
			fmt.Printf("%v-%v\n", i, j)
		}
		// 外层for循环判断
		if breakFlag {
			break
		}
	}
}

使用goto语句能简化代码:

func gotoDemo2() {
	for i := 0; i < 10; i++ {
		for j := 0; j < 10; j++ {
			if j == 2 {
				// 设置退出标签
				goto breakTag
			}
			fmt.Printf("%v-%v\n", i, j)
		}
	}
	return
	// 标签
breakTag:
	fmt.Println("结束for循环")
}
break 跳出循环

break语句可以结束forswitchselect的代码块。
break语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的forswitchselect的代码块上。 举个🌰:

func main() {
breakDEMO:
	for i := 0; i < 10; i++ {
		for j := 0; j < 10; j++ {
			if j == 2 {
				break breakDEMO
			}
			fmt.Printf("%v-%v\n", i, j)
		}
	}
	fmt.Println("...")
}
contine 继续下一个循环

continue语句可以结束当前循环,开始下一次的循环迭代过程,仅限在for循环内使用。
continue语句后添加标签时,表示开始标签对应的循环。举个🌰:

func main() {
forloop:
	for i := 0; i < 5; i++ {
		// forloop2:
		for j := 0; j < 5; j++ {
			if i == 2 && j == 2 {
				continue forloop
			}
			fmt.Printf("%v-%v\n", i, j)
		}
	}
}

3 Go语言数组

Go 语言提供了数组类型的数据结构。

数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形、字符串或者自定义类型。

相对于去声明 number0, number1, …, number99 的变量,使用数组形式 numbers[0], numbers[1] …, numbers[99] 更加方便且易于扩展。

数组元素可以通过索引(位置)来读取(或者修改),索引从 0 开始,第一个元素索引为 0,第二个索引为 1,以此类推。
便于理解

3.1 Array 数组

数组是同一种数据类型元素的集合。 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化。 基本语法:

// 定义一个长度为3元素类型为int的数组a
var a [3]int
3.1.1 数组定义

var 数组变量名 [元素数量]T
比如:var a [5]int, 数组的长度必须是常量,并且长度是数组类型的一部分。一旦定义,长度不能变。[5]int[10]int是不同的类型。

var a [3]int
var b [4]int
a = b //不可以这样做,因为此时a和b是不同的类型

数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1,访问越界(下标在合法范围之外),则触发访问越界(panic)

3.1.2 数组初始化

方法一:初始化数组时可以使用初始化列表来设置数组元素的值。

func main() {
	var testArray [3]int                        //数组会初始化为int类型的零值
	var numArray = [3]int{1, 2}                 //使用指定的初始值完成初始化
	var cityArray = [3]string{"北京", "上海", "深圳"} //使用指定的初始值完成初始化
	fmt.Println(testArray)                      //[0 0 0]
	fmt.Println(numArray)                       //[1 2 0]
	fmt.Println(cityArray)                      //[北京 上海 深圳]
}

方法二:按照上面的方法每次都要确保提供的初始值和数组长度一致,一般情况下我们可以让编译器根据初始值的个数自行推断数组的长度。

func main() {
	var testArray [3]int
	var numArray = [...]int{1, 2}
	var cityArray = [...]string{"北京", "上海", "深圳"}
	fmt.Println(testArray)                          //[0 0 0]
	fmt.Println(numArray)                           //[1 2]
	fmt.Printf("type of numArray:%T\n", numArray)   //type of numArray:[2]int
	fmt.Println(cityArray)                          //[北京 上海 深圳]
	fmt.Printf("type of cityArray:%T\n", cityArray) //type of cityArray:[3]string
}

方法二:使用指定索引值的方式来初始化数组。

func main() {
	a := [...]int{1: 1, 3: 5}
	fmt.Println(a)                  // [0 1 0 5]
	fmt.Printf("type of a:%T\n", a) //type of a:[4]int
}
3.1.3 数组的遍历

两种方法遍历数组,普通forfor range

func main() {
	var a = [...]string{"北京", "上海", "深圳"}
	// 方法1:for循环遍历
	for i := 0; i < len(a); i++ {
		fmt.Println(a[i])
	}

	// 方法2:for range遍历
	for index, value := range a {
		fmt.Println(index, value)
	}
}
3.1.4 数组是值类型

数组是值类型,赋值和传参会复制整个数组。因此改变副本的值,不会改变本身的值。

func modifyArray(x [3]int) {
	x[0] = 100
}

func modifyArray2(x [3][2]int) {
	x[2][0] = 100
}
func main() {
	a := [3]int{10, 20, 30}
	modifyArray(a) //在modify中修改的是a的副本x
	fmt.Println(a) //[10 20 30]
	b := [3][2]int{
		{1, 1},
		{1, 1},
		{1, 1},
	}
	modifyArray2(b) //在modify中修改的是b的副本x
	fmt.Println(b)  //[[1 1] [1 1] [1 1]]
}

注意:

  1. 数组支持 “==“、”!=” 操作符,因为内存总是被初始化过的。
  2. [n]* T表示指针数组,*[n]T表示数组指针 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值