Go语言基础:运算符_流程控制循环_数组_切片
Posted Zeker62
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言基础:运算符_流程控制循环_数组_切片相关的知识,希望对你有一定的参考价值。
文章目录
借鉴了李文周老师的博客
运算符
算数运算符
+ | 相加 |
---|---|
- | 相减 |
* | 相乘 |
/ | 相除 |
% | 求余 |
关系运算符
== | 检查两个值是否相等,如果相等返回 True 否则返回 False。 |
---|---|
!= | 检查两个值是否不相等,如果不相等返回 True 否则返回 False。 |
> | 检查左边值是否大于右边值,如果是返回 True 否则返回 False。 |
>= | 检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。 |
< | 检查左边值是否小于右边值,如果是返回 True 否则返回 False。 |
<= | 检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。 |
位运算符
& | 参与运算的两数各对应的二进位相与。 (两位均为1才为1) |
---|---|
| | 参与运算的两数各对应的二进位相或。 (两位有一个为1就为1) |
^ | 参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。 (两位不一样则为1) |
<< | 左移n位就是乘以2的n次方。 “a<<b”是把a的各二进位全部左移b位,高位丢弃,低位补0。 |
>> | 右移n位就是除以2的n次方。 “a>>b”是把a的各二进位全部右移b位。 |
package main
import "fmt"
// 位运算符
func main() {
a:=5 //0101
b:=6 //0110
//位运算符使用的是二进制运算
// 0101与0110按位与,得到0100=4
fmt.Println(a&b)
// 0101与0110按位或,得到0111=7
fmt.Println(a|b)
// 0101与0110按位异或,得到0011=3
fmt.Println(a^b)
// 0101向左偏移6位,得到0101000000=256+64
fmt.Println(a<<b)
// 如果偏移量超过了数据类型的范围,则多的位数丢弃,比如
var c int8=64
fmt.Println(c<<b) //64为1000000 偏移6位为 1000000000000超过了8位的范围,所以高位舍弃
// 0101与0110向右便宜6位,已经将101偏移出范围了,所以为0
fmt.Println(a>>b)
}
逻辑运算符
&& | 逻辑 AND 运算符。 如果两边的操作数都是 True,则为 True,否则为 False。 |
---|---|
|| | 逻辑 OR 运算符。 如果两边的操作数有一个 True,则为 True,否则为 False。 |
! | 逻辑 NOT 运算符。 如果条件为 True,则为 False,否则为 True。 |
赋值运算符
= | 简单的赋值运算符,将一个表达式的值赋给一个左值 |
---|---|
+= | 相加后再赋值 |
-= | 相减后再赋值 |
*= | 相乘后再赋值 |
/= | 相除后再赋值 |
%= | 求余后再赋值 |
<<= | 左移后赋值 |
>>= | 右移后赋值 |
&= | 按位与后赋值 |
|= | 按位或后赋值 |
^= | 按位异或后赋值 |
流程控制
if语句
if语句的写法相比较于C语言,条件判断的时候没有括号。相比较于Python语言,在条件执行语句的时候具有花括号括起
func main(){
//一般写法
var your_age=18
if your_age<18{
fmt.Println("you are too young!")
}else if 18<=your_age && your_age<35{
fmt.Println("it is the best")
}else{
fmt.Println("you are too old to do this job")
}
fmt.Println("your age is",your_age)
}
if条件判断还有一种特殊的写法,可以在 if 表达式之前添加一个执行语句,再根据变量值进行判断。这种写法会导致此变量的作用域只在条件判断内部,如下所示
func main(){
//特殊写法
if your_age:=18;your_age<18{
fmt.Println("you are too young!")
}else if 18<=your_age && your_age<35{
fmt.Println("it is the best")
}else{
fmt.Println("you are too old to do this job")
}
fmt.Println("your age is",your_age)
}
此时会报错:
# command-line-arguments
.\\if02.go:15:28: undefined: your_age
for循环
Go语言中只有for循环,没有while或者其他循环.
条件表达式返回true
时循环体不停地进行循环,直到条件表达式返回false
时自动退出循环。
一般形式,此时i的作用域是for循环体
func main(){
for i:=0 ;i<10;i++{
fmt.Print(i," ")
}
}
//0 1 2 3 4 5 6 7 8 9
for循环的初始语句可以被忽略,但是初始语句后的分号必须要写,例如:
func main() {
i:=0
for ;i<10;i++{
fmt.Print(i)
}
}
for循环的初始语句和结束语句都可以省略,逐渐向while循环转换,在书写时要防止死循环
func main() {
i:=0
for i<10{
fmt.Print(i)
i++
}
}
for range 键值循环
Go语言中可以使用for range
遍历数组、切片、字符串、map 及通道(channel)。即可以遍历类似于字典这种数据结构, 通过for range
遍历的返回值有以下规律:
- 数组、切片、字符串返回索引和值。
- map返回键和值。
- 通道(channel)只返回通道内的值。
使用range需要有两个变量来接收,如果使用一个变量接收的话,就只接收索引
func main() {
var l =[3]int{1,2,3}
for a,b :=range l{
fmt.Printf("%d:%d\\n",a,b)
}
}
//0:1
//1:2
//2:3
一个变量进行接收
func main() {
var l =[3]int{1,2,3}
for b :=range l{
fmt.Printf("%d\\n",b)
}
}
//0
//1
//2
Swith 语句
使用switch
语句可方便地对大量的值进行条件判断。
func switchDemo1() {
finger := 3
switch finger {
case 1:
fmt.Println("大拇指")
case 2:
fmt.Println("食指")
case 3:
fmt.Println("中指")
case 4:
fmt.Println("无名指")
case 5:
fmt.Println("小拇指")
default:
fmt.Println("无效的输入!")
}
}
Go语言规定每个switch
只能有一个default
分支。
一个分支可以有多个值,多个case值中间使用英文逗号分隔。
func testSwitch2() {
switch n := 7; n { //注意此时n的作用域
case 1, 3, 5, 7, 9:
fmt.Println("奇数")
case 2, 4, 6, 8:
fmt.Println("偶数")
default:
fmt.Println(n)
}
}
分支还可以使用表达式,这时候switch语句后面不需要再跟判断变量。例如:
func switchDemo4() {
age := 30
switch {
case age < 25:
fmt.Println("好好学习吧")
case age > 25 && age < 35:
fmt.Println("好好工作吧")
case age > 60:
fmt.Println("好好享受吧")
default:
fmt.Println("活着真好")
}
}
fallthrough
语法可以执行满足条件的case的下一个case,是为了兼容C语言中的case设计的。(不常用)
func switchDemo5() {
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("...")
}
}
goto跳转(不常用)
goto
语句通过标签进行代码间的无条件跳转。goto
语句可以在快速跳出循环、避免重复退出上有一定的帮助。Go语言中使用goto
语句能简化一些代码的实现过程。
package main
import "fmt"
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循环")
}
func main() {
gotoDemo2()
}
break和continue
break
语句可以结束for
、switch
和select
的代码块。
break
语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的for
、switch
和 select
的代码块上。 举个例子:
func breakDemo1() {
BREAKDEMO1:
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if j == 2 {
break BREAKDEMO1
}
fmt.Printf("%v-%v\\n", i, j)
}
}
fmt.Println("...")
}
continue
语句可以结束当前循环,开始下一次的循环迭代过程,仅限在for
循环内使用。
在 continue
语句后添加标签时,表示开始标签对应的循环。例如:
func continueDemo() {
forloop1:
for i := 0; i < 5; i++ {
// forloop2:
for j := 0; j < 5; j++ {
if i == 2 && j == 2 {
continue forloop1
}
fmt.Printf("%v-%v\\n", i, j)
}
}
}
数组
数组是同一种数据类型元素的集合。 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化。即当时定义了容量为多大的数组,这个容量就不可再变化
数组定义
Go语言数组的定义和其他语言都不太一致,具体格式为:
var 数组名 [数组大小]数组内成员数据类型
比如
var array [3]int
这就定义了名为array,大小为3,int类型的数组
数组初始化
直接/一般初始化
数组在定义的时候就可以直接初始化:
格式为
var 数组名 = [数组大小]数组内成员数据类型{数组值且用逗号分隔}
数组名 := [数组大小]数组内成员数据类型{数组值且用逗号分隔}
例如
var array= [3]int{1,2,3}
fmt.Print(array)
//[1 2 3]
a := [3]int{10, 20, 30}
部分/默认值初始化
如果不初始化数组或者部分初始化,那么没初始化的成员会具有默认值
func main() {
// 数组定义
var array[3]int
var array_string[3]string
var array_string_2=[4]string{"上海","北京"}
var array_bool[3]bool
var array_int=[3]int{1,2}
fmt.Println(array)
fmt.Println(array_string)
fmt.Println("部分初始化",array_string_2)
fmt.Println(array_bool)
fmt.Println("部分初始化:",array_int)
}
//[0 0 0]
//[ ]
//部分初始化 [上海 北京 ]
//[false false false]
//部分初始化: [1 2 0]
不确定初始化
当数组的大小不确定时,可以用[…]进行省略,系统会自动分配合适的空间给数组
package main
import "fmt"
func main() {
var array[3]int
var array_string_2=[...]string{"上海","北京"}
var array_bool[3]bool
var array_int=[...]int{1,2}
fmt.Println(array)
fmt.Println("不确定初始化",array_string_2)
fmt.Println(array_bool)
fmt.Println("不确定初始化:",array_int)
}
此外,不确定符号只能用于初始化,不能用于定义,如下的行为就是错误的
var array_string[...]string
索引值初始化
也可以直接通过索引值给数组初始化:
func main() {
var array=[7]int{1:2,5:100,2:10}
var array2=[...]int{1:2,20:10}
fmt.Print(array," ")
fmt.Printf("type of array2:%T \\n",array)
fmt.Print(array2," ")
fmt.Printf("type of array2:%T",array2)
}
//[0 2 10 0 0 100 0] type of array2:[7]int
//[0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10] type of array2:[21]int
数组遍历
数组的遍历无异于要使用循环结构,下面介绍两种循环结构遍历数组
package main
import "fmt"
func main() {
var array=[...]int{1,2,3,4,5,6,7,8,9,10}
//len函数可以获取数组长度
fmt.Println("使用for循环遍历数组array")
for i:=0;i<len(array);i++{
fmt.Print(array[i]," ")
}
fmt.Println("\\n使用for range循环遍历数组")
for _,a:=range array{
fmt.Print(a," ")
}
}
//使用for循环遍历数组array
//1 2 3 4 5 6 7 8 9 10
//使用for range循环遍历数组
//1 2 3 4 5 6 7 8 9 10
多维数组
以二维数组为例
二维数组定义和初始化
和其他语言的二维数组定义模板类似:
var array=[3][2]int{{1,2},{3,4},{5,6}}
此外,定义的时候只有第一层可以使用[…],例如
var array2=[...][2]int{{1,2},{3,4},{5,6},{7,8}}
fmt.Println(array2) //[[1 2] [3 4] [5 6] [7 8]]
fmt.Println(len(array2)) //4
这种行为时不可取的
var array2=[...][...]int{{1,2},{3,4},{5,6},{7,8}}
var array3=[4][...]int{{1,2},{3,4},{5,6},{7,8}}
二维数组遍历
两层循环嵌套,这里演示一下for和for range循环嵌套
package main
import "fmt"
func main() {
var array2=[...][2]int{{1,2},{3,4},{5,6},{7,8}}
for i:=0;i<len(array2);i++{
for _,a:=range array2[i]{
fmt.Print(a,"\\t")
}
fmt.Println()
}
}
//1 2
//3 4
//5 6
//7 8
值类型和引用类型
- 数组是值类型,即当数组进行复制的时候,会额外开辟一个内存空间,这两个内存空间互不干扰,一方发生变化不会影响到另一方。
- 引用类型指的是指针,即浅复制,开辟一个内存空间不存放原来的数值,而是存放该目标的地址,一方发生变化,就会影响到另一方。
package main
import "fmt"
func change(a [3]int) {
a[2]=22
fmt.Println("在函数体内部时",a)
}
func main() {
var array=[3]int{1,2,3Go基础2