Golang学习笔记部分二

Golang运算符

Go 语言内置的运算符有:

  1. 算术运算符
  2. 关系运算符
  3. 逻辑运算符
  4. 位运算符
  5. 赋值运算符

算术运算符

运算符 描述
+ 相加
- 相减
* 相乘
/ 相除
% 求余

注意: ++(自增)和 --(自减)在Go语言中是单独的语句,并不是运算符。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import "fmt"

func main() {
a := 100
b := 10

fmt.Printf("(a + b): %v\n", (a + b))
fmt.Printf("(a - b): %v\n", (a - b))
fmt.Printf("(a * b): %v\n", (a * b))
fmt.Printf("(a / b): %v\n", (a / b))
fmt.Printf("(a %% b): %v\n", (a % b))

a++
fmt.Printf("a: %v\n", a)
b--
fmt.Printf("b: %v\n", b)
}

关系运算符

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

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

func main() {
a := 1
b := 2

fmt.Printf("(a > b): %v\n", (a > b))
fmt.Printf("(a < b): %v\n", (a < b))
fmt.Printf("(a >= b): %v\n", (a >= b))
fmt.Printf("(a <= b): %v\n", (a <= b))
fmt.Printf("(a == b): %v\n", (a == b))
fmt.Printf("(a != b): %v\n", (a != b))
}

逻辑运算符

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

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import "fmt"

func main() {
a := true
b := false

fmt.Printf("(a && b): %v\n", (a && b))
fmt.Printf("(a || b): %v\n", (a || b))
fmt.Printf("(!a): %v\n", (!a))
fmt.Printf("(!b): %v\n", (!b))
}

位运算符

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

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

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import "fmt"

func main() {
a := 4 // 二进制 100
fmt.Printf("a: %b\n", a)
b := 8 // 二进制 1000
fmt.Printf("b: %b\n", b)

fmt.Printf("(a & b): %v, %b \n", (a & b), (a & b))
fmt.Printf("(a | b): %v, %b\n", (a | b), (a | b))
fmt.Printf("(a ^ b): %v, %b\n", (a ^ b), (a ^ b))
fmt.Printf("(a << 2): %v, %b\n", (a << 2), (a << 2))
fmt.Printf("(b >> 2): %v, %b\n", (b >> 2), (b >> 2))
}

赋值运算符

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

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import "fmt"

func main() {
var a int
a = 100
fmt.Printf("a: %v\n", a)
a += 1 // a = a + 1
fmt.Printf("a: %v\n", a)
a -= 1 // a = a -1
fmt.Printf("a: %v\n", a)
a *= 2 // a = a * 2
fmt.Printf("a: %v\n", a)
a /= 2 // a = a / 2
fmt.Printf("a: %v\n", a)
}

Go语言中的流程控制

Go语言中的条件

条件语句 是用来判断给定的条件是否满足(表达式值是否为 true或者 false),并根据判断的结果(真或假)决定执行的语句,go语言中的条件语句也是这样的。

Go语言中的条件语句包含如下几种情况

  1. if 语句if 语句 由一个布尔表达式后紧跟一个或多个语句组成。
  2. if…else 语句 :if 语句 后可以使用可选的else 语句,else 语句中的表达式在布尔表达式为false 时执行。
  3. if 嵌套语句 : 你可以在ifelse if 语句中嵌入一个或多个ifelse if 语句。
  4. switch 语句 :switch 语句用于基于不同条件执行不同动作。
  5. select 语句 :select 语句类似于switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。

Go语言中的循环语句

go语言中的循环只有for循环,去除了 whiledo while循环,使用起来更加简洁。

  1. for循环。
  2. for range循环。

Go语言中的流程控制关键字

  1. break
  2. continue
  3. goto

Golang中的if语句

Go语言 中的if语句 和其他语言中的类似,都是根据给定的条件表达式运算结果来,判断执行流程。

Go语言if语句语法

1
2
3
if 布尔表达式 {
/* 在布尔表达式为 true 时执行 */
}

注意:在go语言中 布尔表达式不用使用括号。

Go语言if语句实例演示

根据布尔值flag判断

1
2
3
4
5
6
7
8
9
10
11
12
13
import "fmt"

func test1() {
var flag = true
if flag {
fmt.Println("flag is true")
}
fmt.Printf("程序运行结束")
}

func main() {
test1()
}

程序运行结果

1
2
flag is true
程序运行结束

根据年龄判断是否成年

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

func test2() {
var age = 20
if age > 18 {
fmt.Println("你是成年人")
}
fmt.Printf("程序运行结束")
}

func main() {
test2()
}

程序运行结果

1
2
你是成年人
程序运行结束

初始变量可以声明在布尔表达式里面,注意它的作用域

1
2
3
4
5
6
7
8
9
10
11
12
func test3() {
if age := 20; age > 18 {
fmt.Println("你是成年人")
}
fmt.Printf("程序运行结束")
}

func main() {
// test1()
// test2()
test3()
}

程序运行结果

1
2
你是成年人
程序运行结束

注意:不能使用0或非0表示真假

1
2
3
4
5
6
7
func test4() {
var i = 1
if i { // 编译失败
fmt.Println("here")
}
fmt.Printf("程序运行结束")
}

go语言if语句使用提示:

  1. 不需使用括号将条件包含起来
  2. 大括号{}必须存在,即使只有一行语句
  3. 左括号必须在ifelse的同一行
  4. if之后,条件语句之前,可以添加变量初始化语句,使用进行分隔

Golang中的if else语句

go语言中的if else语句可以根据给定条件二选一

Go语言的if else语句语法

1
2
3
4
5
if 布尔表达式 {
/* 在布尔表达式为 true 时执行 */
} else {
/* 在布尔表达式为 false 时执行 */
}

Go语言if else语句实例

比较两个数的大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import "fmt"

func f1() {
a := 1
b := 2
if a > b {
fmt.Printf("\"a>b\": %v\n", "a>b")
} else {
fmt.Printf("\"a<=b\": %v\n", "a<b")
}
}

func main() {
f1()
}

判断一个数是奇数还是偶数

1
2
3
4
5
6
7
8
9
10
11
12
func f2() {
var s int
fmt.Println("输入一个数字:")
fmt.Scan(&s)

if s%2 == 0 {
fmt.Print("s 是偶数\n")
} else {
fmt.Print("s 不是偶数\n")
}
fmt.Print("s 的值是:", s)
}

判断一个人是否成年

1
2
3
4
5
6
7
8
func f3() {
age := 20
if age >= 18 {
fmt.Println("你是成年人")
} else {
fmt.Println("你还未成年")
}
}

特殊写法,在if前面添加执行语句

1
2
3
4
5
6
7
func f4() {
if age := 20; age >= 18 {
fmt.Println("你是成年人")
} else {
fmt.Println("你还未成年")
}
}

go语言if语句使用提示:

  1. 不需使用括号将条件包含起来
  2. 大括号{}必须存在,即使只有一行语句
  3. 左括号 必须在ifelse的同一行
  4. if之后,条件语句之前,可以添加变量初始化语句 ,使用进行分隔。

Golang中的if else if语句

go语言if语句可以进行多重嵌套使用,进行多重判断。

Go语言中的if else if语法

1
2
3
4
5
6
7
if 布尔表达式1 {
// do something
} else if 布尔表达式2 {
// do something else
}else {
// catch-all or default
}

Go语言中的if else if语法实例

根据分数判断等级

1
2
3
4
5
6
7
8
9
10
func f5() {
score := 80
if score >= 60 && score <= 70 {
fmt.Println("C")
} else if score > 70 && score <= 90 {
fmt.Println("B")
} else {
fmt.Println("A")
}
}

程序运行结果

1
B

同样也可以写成这样

1
2
3
4
5
6
7
8
9
func f5() {
if score := 80; score >= 60 && score <= 70 {
fmt.Println("C")
} else if score > 70 && score <= 90 {
fmt.Println("B")
} else {
fmt.Println("A")
}
}

输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续判断第二个字母

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
func f6() {
// Monday Tuesday Wednesday Thursday Friday Saturday Sunday
var c string
fmt.Println("输入一个字符:")
fmt.Scan(&c)

if c == "S" {
fmt.Println("输入第二个字符:")
fmt.Scan(&c)
if c == "a" {
fmt.Println("Saturday")
} else if c == "u" {
fmt.Println("Sunday")
} else {
fmt.Println("输入错误")
}
} else if c == "F" {
fmt.Println("Friday")
} else if c == "M" {
fmt.Println("Monday")
} else if c == "T" {
fmt.Println("输入第二个字符:")
fmt.Scan(&c)
if c == "u" {
fmt.Println("Tuesday")
} else if c == "h" {
fmt.Println("Thursday")
} else {
fmt.Println("输入错误")
}
} else if c == "W" {
fmt.Println("Wednesday")
} else {
fmt.Println("输入错误")
}
}

Golang中嵌套if语句

go语言if语句可以嵌套多级进行判断。

Go语言if嵌套语法

1
2
3
4
5
6
if 布尔表达式 1 {
/* 在布尔表达式 1 为 true 时执行 */
if 布尔表达式 2 {
/* 在布尔表达式 2 为 true 时执行 */
}
}

Go语言if嵌套实例

判断三个数的大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import "fmt"

// a>b a>c a
// b>a b>c b else c

func f1() {
a := 100
b := 200
c := 3
if a > b {
if a > c {
fmt.Println("a最大")
}
} else {
if b > c {
fmt.Println("b最大")
} else {
fmt.Println("c最大")
}
}
}

func main() {
f1()
}

判断男生还是女生,还有是否成年

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func f2() {
// 判断男女生及年龄
gender := "女生"
age := 16
if gender == "男生" {
fmt.Println("男生")
if age > 18 {
fmt.Println("成年")
} else {
fmt.Println("未成年")
}
} else {
fmt.Println("女生")
if age > 18 {
fmt.Println("成年")
} else {
fmt.Println("未成年")
}
}
}

Golang switch语句

go语言中的 switch语句,可以非常容易的判断多个值的情况。

Go语言中switch语句的语法

1
2
3
4
5
6
7
8
switch var1 {
case val1:
...
case val2:
...
default:
...
}

Go语言中 switch语句实例

判断成绩

1
2
3
4
5
6
7
8
9
10
11
func f() {
grade := "A"
switch grade {
case "A":
fmt.Println("优秀")
case "B":
fmt.Println("良好")
default:
fmt.Println("一般")
}
}

运行结果

1
优秀

多条件匹配

Go语言 switch语句,可以同时匹配多个条件,中间用逗号分隔,有其中一个匹配成功即可。

1
2
3
4
5
6
7
8
9
func f() {
day := 3
switch day {
case 1, 2, 3, 4, 5:
fmt.Println("工作日")
case 6, 7:
fmt.Println("休息日")
}
}

运行结果

1
工作日

case可以是条件表达式

1
2
3
4
5
6
7
8
9
10
11
func f() {
score := 90
switch {
case score >= 90:
fmt.Println("享受假期")
case score < 90 && score >= 80:
fmt.Println("好好学习吧!")
default:
fmt.Println("玩命学习!")
}
}

运行结果

1
享受假期

fallthrough可以可以执行满足条件的下一个 case

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func f3() {
a := 100
switch a {
case 100:
fmt.Println("100")
fallthrough
case 200:
fmt.Println("200")
case 300:
fmt.Println("300")
default:
fmt.Println("other")
}
}

运行结果

1
2
100
200

Go语言中 switch语句的注意事项

  1. 支持多条件匹配
  2. 不同的case 之间不使用break 分隔,默认只会执行一个case
  3. 如果想要执行多个case,需要使用fallthrough 关键字,也可用break 终止。
  4. 分支还可以使用表达式 ,例如:a>10.

Golang for循环语句

go语言中的 for循环,只有 for关键字,去除了像其他语言中的 whiledo while.

Go语言for循环语法

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

注意:for表达式不用加括号

Go语言for循环实例

循环输出1到10

1
2
3
4
5
func f() {
for i := 1; i <= 10; i++ {
fmt.Printf("i: %v\n", i)
}
}

运行结果

1
2
3
4
5
6
7
8
9
10
i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
i: 7
i: 8
i: 9
i: 10

初始条件,可以写到外面

1
2
3
4
5
6
func f() {
i := 1
for ; i <= 10; i++ {
fmt.Printf("i: %v\n", i)
}
}

运行结果

1
2
3
4
5
6
7
8
9
10
i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
i: 7
i: 8
i: 9
i: 10

初始条件和结束条件都可以省略

1
2
3
4
5
6
7
func f() {
i := 1 // 初始条件
for i <= 10 {
fmt.Printf("i: %v\n", i)
i++ // 结束条件
}
}

运行结果

1
2
3
4
5
6
7
8
9
10
i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
i: 7
i: 8
i: 9
i: 10

这种情况类似其他语言中的 while循环

永真循环

1
2
3
4
5
6
7
8
9
func f() {
for {
fmt.Println("我一直在执行~")
}
}

func main() {
f()
}

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
我一直在执行~
我一直在执行~
我一直在执行~
我一直在执行~
我一直在执行~
我一直在执行~
我一直在执行~
我一直在执行~
我一直在执行~
我一直在执行~
我一直在执行~
我一直在执行~
我一直在执行~
我一直在执行~
......

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

Golang for range循环

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

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

Go语言for range实例

循环数组

1
2
3
4
5
6
7
8
9
10
func f() {
var a = [5]int{1, 2, 3, 4, 5}
for i, v := range a {
fmt.Printf("i: %d, v: %v\n", i, v)
}
}

func main() {
f()
}

运行结果

1
2
3
4
5
i: 0, v: 1
i: 1, v: 2
i: 2, v: 3
i: 3, v: 4
i: 4, v: 5

循环字符串

1
2
3
4
5
6
7
8
9
10
11
func f() {
var s = "多课网,go教程"
for i, v := range s {
fmt.Printf("i: %d, v: %c\n", i, v)
}
// %c 按照字符输出
}

func main() {
f()
}

运行结果

1
2
3
4
5
6
7
8
i: 0, v: 多
i: 3, v: 课
i: 6, v: 网
i: 9, v: ,
i: 12, v: g
i: 13, v: o
i: 14, v: 教
i: 17, v: 程

循环切片

1
2
3
4
5
6
7
8
9
10
func f() {
var s = []int{1, 2, 3, 4, 5}
for i, v := range s {
fmt.Printf("i, %d, v: %v\n", i, v)
}
}

func main() {
f()
}

循环map

1
2
3
4
5
6
7
8
9
10
11
12
13
func f() {
m := make(map[string]string)
m["name"] = "tom"
m["age"] = "20"
m["email"] = "[email protected]"
for k, v := range m {
fmt.Printf("k: %v, v: %v\n", k, v)
}
}

func main() {
f()
}

运行结果

1
2
3
k: email, v: [email protected]
k: name, v: tom
k: age, v: 20

Golang流程控制关键字break

break语句可以结束 forswitchselect的代码块。

Go语言使用break注意事项

  1. 单独在select中使用break和不使用break没有啥区别。
  2. 单独在表达式switch语句,并且没有fallthough,使用break和不使用break没有啥区别。
  3. 单独在表达式switch语句,并且有fallthough,使用break能够终止fallthough后面的case语句的执行。
  4. 带标签的break,可以跳出多层select/ switch作用域。让break更加灵活,写法更加简单灵活,不需要使用控制变量一层一层跳出循环,没有带break的只能跳出当前语句块。

Go语言break关键字实例

跳出for循环

1
2
3
4
5
6
7
8
9
10
11
12
func f() {
for i := 0; i < 10; i++ {
if i == 5 {
break // 退出循环
}
fmt.Printf("i: %v\n", i)
}
}

func main() {
f()
}

运行结果

1
2
3
4
5
i: 0
i: 1
i: 2
i: 3
i: 4

跳出switch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func f() {
i := 2
switch i {
case 1:
fmt.Println("等于1")
break
case 2:
fmt.Println("等于2")
break
fallthrough
case 3:
fmt.Println("等于3")
break
default:
fmt.Println("不关心")
break
}
}
func main() {
f()
}

运行结果

1
等于2

注释掉 fallthrough上面的 break,运行结果

1
2
等于2
等于3

跳转到标签处

1
2
3
4
5
6
7
8
9
10
11
12
13
func f() {
MY_LABEL:
for i := 0; i < 10; i++ {
if i == 5 {
break MY_LABEL
}
fmt.Printf("%v\n", i)
}
fmt.Println("end...")
}
func main() {
f()
}

运行结果

1
2
3
4
5
6
0
1
2
3
4
end...

Golang关键字continue

continue只能用在循环中,在go中只能用在 for循环中,它可以终止本次循环,进行下一次循环。

continue语句后添加标签时,表示开始标签对应的循环。

Go语言 continue实例

输出1到10之间的偶数

1
2
3
4
5
6
7
8
9
10
func f() {
for i := 0; i < 10; i++ {
if i%2 == 0 {
fmt.Printf("i: %v\n", i)
}
}
}
func main() {
f()
}

运行结果

1
2
3
4
5
i: 0
i: 2
i: 4
i: 6
i: 8

跳转到label

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func f() {
// MY_LABEL:
for i := 0; i < 5; i++ {
MY_LABEL:
for j := 0; j < 5; j++ {
if i == 2 && j == 2 {
continue MY_LABEL
}
fmt.Printf("i=%d,j=%d\n", i, j)
}
}
}
func main() {
f()
}

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
i=0,j=0
i=0,j=1
i=0,j=2
i=0,j=3
i=0,j=4
i=1,j=0
i=1,j=1
i=1,j=2
i=1,j=3
i=1,j=4
i=2,j=0
i=2,j=1
i=2,j=3
i=2,j=4
i=3,j=0
i=3,j=1
i=3,j=2
i=3,j=3
i=3,j=4
i=4,j=0
i=4,j=1
i=4,j=2
i=4,j=3
i=4,j=4

Golang流程控制关键字goto

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

Go语言关键字goto实例

跳转到指定标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func f() {
a := 0
if a == 1 {
goto LABEL1
} else {
fmt.Println("other")
}

LABEL1:
fmt.Printf("next...")
}

func main() {
f()
}

运行结果

1
next...

跳出双重循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func f() {
for i := 0; i < 5; i++ {
for j := 0; j < 5; j++ {
if i == 2 && j == 2 {
goto LABEL1
}
}
}
LABEL1:
fmt.Println("label1")
}

func main() {
f()
}

运行结果

1
label1

Golang数组

数组是相同数据类型 的一组数据的集合,数组一旦定义长度不能修改 ,数组可以通过 下标(或者叫索引) 来访问元素。

Go语言数组的定义

数组定义的语法如下:

1
var variable_name [SIZE] variable_type

variable_name:数组名称

SIZE:数组长度,必须是常量

variable_type:数组保存元素的类型

实例

1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"

func main() {
var a [3]int // 定义一个int类型的数组a,长度是3
var s [2]string // 定义一个字符串类型的数组s,长度是2

fmt.Printf("a: %T\n", a)
fmt.Printf("s: %T\n", s)
}

运行结果

1
2
a: [3]int
s: [2]string

从上面运行结果,我们可以看出,数组和长度和元素类型共同组成了数组的类型。

Go语言数组的初始化

初始化,就是给数组的元素赋值,没有初始化的数组,默认元素值都是零值 ,布尔类型是 false,字符串是空字符串。

没有初始化的数组

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import "fmt"

func main() {
var a [3]int // 定义一个int类型的数组a,长度是3
var s [2]string // 定义一个字符串类型的数组s,长度是2
var b [2]bool

fmt.Printf("a: %v\n", a)
fmt.Printf("s: %v\n", s)
fmt.Printf("b: %v\n", b)
}

运行结果

1
2
3
a: [0 0 0]
s: ["" ""]
b: [false false]

使用初始化列表

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import "fmt"

func main() {
var a = [3]int{1, 2, 3}
var s = [2]string{"tom", "kite"}
var b = [2]bool{true, false}

a1 := [2]int{1, 2} // 类型推断

fmt.Printf("a: %v\n", a)
fmt.Printf("s: %v\n", s)
fmt.Printf("b: %v\n", b)
fmt.Printf("a1: %v\n", a1)
}

运行结果

1
2
3
4
a: [1 2 3]
s: [tom kite]
b: [true false]
a1: [1 2]

使用初始化列表,就是将值写在大括号 里面。

省略数组长度

数组长度可以省略,使用 ...代替,更加初始化值得数量自动推断 ,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import "fmt"

func main() {
var a = [...]int{1, 2, 3}
var s = [...]string{"tom", "kite"}
var b = [...]bool{true, false}

a1 := [...]int{1, 2} // 类型推断

fmt.Printf("a: %v\n", a)
fmt.Printf("s: %v\n", s)
fmt.Printf("b: %v\n", b)
fmt.Printf("a1: %v\n", a1)
}

运行结果

1
2
3
4
a: [1 2 3]
s: [tom kite]
b: [true false]
a1: [1 2]

指定索引值的方式来初始化

可以通过指定所有的方式来初始化,未指定所有的默认未零值。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import "fmt"

func main() {
var a = [...]int{0: 1, 2: 2}
var s = [...]string{1: "tom", 2: "kite"}
var b = [...]bool{2: true, 5: false}

a1 := [...]int{1, 2} // 类型推断

fmt.Printf("a: %v\n", a)
fmt.Printf("s: %v\n", s)
fmt.Printf("b: %v\n", b)
fmt.Printf("a1: %v\n", a1)
}

运行结果

1
2
3
4
a: [1 0 2]
s: [ tom kite]
b: [false false true false false false]
a1: [1 2]

GoLang访问数组元素

可以通过下标的方式,来访问数组元素。数组的最大下标为数组长度-1,大于这个下标会发生数组越界。

访问数组元素

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "fmt"

func main() {
var a [2]int
a[0] = 100
a[1] = 200

fmt.Printf("a[0]: %v\n", a[0])
fmt.Printf("a[0]: %v\n", a[1])

// 修改 a[0] a[1]
a[0] = 1
a[1] = 2

fmt.Println("-----------")

fmt.Printf("a[0]: %v\n", a[0])
fmt.Printf("a[0]: %v\n", a[1])
}

运行结果

1
2
3
4
5
a[0]: 100
a[0]: 200
-----------
a[0]: 1
a[0]: 2

根据数组长度遍历数组

可以根据数组长度,通过 for循环的方式来遍历数组,数组的长度可以使用 len函数获得。

实例

1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"

func main() {
a := [...]int{1, 2, 3, 4, 5, 6}

for i := 0; i < len(a); i++ {
fmt.Printf("a[%d]: %v\n", i, a[i])
}
}

运行结果

1
2
3
4
5
6
a[0]: 1
a[1]: 2
a[2]: 3
a[3]: 4
a[4]: 5
a[5]: 6

使用 for range数组

还可以使用 for range循环来遍历数组,range返回数组下标和对应的值

实例

1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"

func main() {
a := [...]int{1, 2, 3, 4, 5, 6}

for i, v := range a {
fmt.Printf("a[%d]: %v\n", i, v)
}
}

运行结果

1
2
3
4
5
6
a[0]: 1
a[1]: 2
a[2]: 3
a[3]: 4
a[4]: 5
a[5]: 6

Golang切片

前面我们学习了数组,数组是固定长度,可以容纳相同数据类型的元素的集合。当长度固定时,使用还是带来一些限制,比如:我们申请的长度太大浪费内存,太小又不够用。

鉴于上述原因,我们有了go语言的切片,可以把切片理解为,可变长度的数组,其实它底层就是使用数组实现的,增加了自动扩容 功能。切片(Slice)是一个拥有相同类型元素的可变长度的序列。

Go语言切片的语法

声明一个切片和声明一个数组类似,只要不添加长度就可以了

1
var identifier []type

切片是引用类型,可以使用 make函数来创建切片:

1
2
3
4
5
var slice1 []type = make([]type, len)

也可以简写为

slice1 := make([]type, len)

也可以指定容量,其中capacity为可选参数。

1
make([]T, length, capacity)

这里 len 是数组的长度并且也是切片的初始长度。

Go语言切片实例

1
2
3
4
5
6
7
8
9
10
11
12
package main

import "fmt"

func main() {
var names []string
var numbers []int
fmt.Printf("names: %v\n", names)
fmt.Printf("numbers: %v\n", numbers)
fmt.Println(names == nil)
fmt.Println(numbers == nil)
}

运行结果

1
2
3
4
names: []
numbers: []
true
true

Go语言切片的长度和容量

切片拥有自己的长度和容量,我们可以通过使用内置的 len()函数求长度,使用内置的 cap()函数求切片的容量。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import "fmt"

func main() {
var names = []string{"tom", "kite"}
var numbers = []int{1, 2, 3}

fmt.Printf("len: %d cap: %d\n", len(names), cap(names))
fmt.Printf("len: %d cap: %d\n", len(numbers), cap(numbers))

var s1 = make([]string, 2, 3)
fmt.Printf("len: %d cap: %d\n", len(s1), cap(s1))
}

运行结果

1
2
3
len: 2 cap: 2
len: 3 cap: 3
len: 2 cap: 3

Golang切片的初始化

切片的初始化方法很多,可以直接初始化,也可以使用数组初始化等。

切片如何切分

1
2
3
4
5
6
7
8
9
10
11
12
// 切片
func test1() {
var s1 = []int{1, 2, 3, 4, 5, 6}
s2 := s1[0:3] // [)
fmt.Printf("s2: %v\n", s2)
s3 := s1[3:]
fmt.Printf("s3: %v\n", s3)
s4 := s1[2:5]
fmt.Printf("s4: %v\n", s4)
s5 := s1[:]
fmt.Printf("s5: %v\n", s5)
}

直接初始化

1
2
3
4
5
6
7
8
package main

import "fmt"

func main() {
s := []int{1, 2, 3}
fmt.Printf("s: %v\n", s)
}

运行结果

1
s: [1 2 3]

使用数组初始化

1
2
3
4
5
6
7
8
9
package main

import "fmt"

func main() {
arr := [...]int{1, 2, 3}
s1 := arr[:]
fmt.Printf("s1: %v\n", s1)
}

运行结果

1
s1: [1 2 3]

使用数组的部分元素初始化(切片表达式)

切片的底层就是一个数组 ,所以我们可以基于数组通过切片表达式得到切片 。 切片表达式中的low和high表示一个索引范围(左包含,右不包含 ),得到的切片长度 =high-low,容量等于得到的切片的底层数组的容量。

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import "fmt"

func main() {
arr := [...]int{1, 2, 3, 4, 5, 6}
s1 := arr[2:5]
fmt.Printf("s1: %v\n", s1)
s2 := arr[2:]
fmt.Printf("s2: %v\n", s2)
s3 := arr[:3]
fmt.Printf("s3: %v\n", s3)
}

运行结果

1
2
3
s1: [3 4 5]
s2: [3 4 5 6]
s3: [1 2 3]

空(nil)切片

一个切片在未初始化之前默认为 nil,长度为 0,容量为0.

1
2
3
4
5
6
7
8
9
package main

import "fmt"

func main() {
var s1 []int
fmt.Println(s1 == nil)
fmt.Printf("len: %d, cap: %d\n", len(s1), cap(s1))
}

运行结果

1
2
true
len: 0, cap: 0

Go语言切片的遍历

切片的遍历和数组的遍历非常类似,可以使用for循环索引遍历,或者for range循环。

for循环索引遍历

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"

func main() {
s1 := []int{1, 2, 3, 4, 5}
for i := 0; i < len(s1); i++ {
fmt.Printf("s1[%d]: %v\n", i, s1[i])
}
}

运行结果

1
2
3
4
5
s1[0]: 1
s1[1]: 2
s1[2]: 3
s1[3]: 4
s1[4]: 5

for range循环

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"

func main() {
s1 := []int{1, 2, 3, 4, 5}
for i, v := range s1 {
fmt.Printf("s1[%d]: %v\n", i, v)
}
}

运行结果

1
2
3
4
5
s1[0]: 1
s1[1]: 2
s1[2]: 3
s1[3]: 4
s1[4]: 5

Go语言切片元素的添加和删除copy

切片是一个动态数组,可以使用 append()函数添加元素,go语言中并没有删除切片元素的专用方法,我们可以使用切片本身的特性来删除元素。由于,切片是引用类型,通过赋值的方式,会修改原有内容,go提供了 copy()函数来拷贝切片

db CRUD

添加元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import "fmt"

func main() {
s1 := []int{}
s1 = append(s1, 1)
s1 = append(s1, 2)
s1 = append(s1, 3, 4, 5) // 添加多个元素
fmt.Printf("s1: %v\n", s1)

s3 := []int{3, 4, 5}
s4 := []int{1, 2}
s4 = append(s4, s3...) // 添加另外一个切片
fmt.Printf("s4: %v\n", s4)
}

运行结果

1
2
s1: [1 2 3 4 5]
s4: [1 2 3 4 5]

删除元素

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"

func main() {
s1 := []int{1, 2, 3, 4, 5}
// 删除索引为2的元素
s1 = append(s1[:2], s1[3:]...)
fmt.Printf("s1: %v\n", s1)
}

运行结果

1
s1: [1 2 4 5]

公式:要从切片a中删除索引为 index的元素,操作方法是 a = append(a[:index], a[index+1:]...)

拷贝切片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "fmt"

func main() {
s1 := []int{1, 2, 3}
s2 := s1
s1[0] = 100
fmt.Printf("s1: %v\n", s1)
fmt.Printf("s2: %v\n", s2)
fmt.Println("----------")

s3 := make([]int, 3)

copy(s3, s1)

s1[0] = 1

fmt.Printf("s1: %v\n", s1)
fmt.Printf("s3: %v\n", s3)
}

运行结果

1
2
3
4
5
s1: [100 2 3]
s2: [100 2 3]
-------------
s1: [1 2 3]
s3: [100 2 3]

从运行结果,我们看到赋值的情况下,原来的变量被修改了,使用copy函数,原来的变量没有被修改。

Golang map

map是一种 key:value键值对的数据结构容器。map内部实现是哈希表(hash)。

map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。

map是引用类型的。

map的语法格式

可以使用内建函数 make 也可以使用 map 关键字来定义 map

1
2
3
4
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type
/* 使用 make 函数 */
map_variable = make(map[key_data_type]value_data_type)

map_variable:map变量名称

key_data_type:key的数据类型

value_data_type:值得数据类型

实例

下面声明一个保存个人信息的map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import "fmt"

func main() {
m1 := make(map[string]string)
m1["name"] = "tom"
m1["age"] = "20"
m1["email"] = "[email protected]"

fmt.Printf("m1: %v\n", m1)

m2 := map[string]string{
"name": "kite",
"age": "20",
"email": "[email protected]",
}

fmt.Printf("m2: %v\n", m2)
}

运行结果

1
2
m1: map[age:20 email:[email protected] name:tom]
m2: map[age:20 email:[email protected] name:kite]

访问map

可以通过下标key获得其值,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import "fmt"

func main() {
m1 := make(map[string]string)
m1["name"] = "tom"
m1["age"] = "20"
m1["email"] = "[email protected]"

name := m1["name"]
age := m1["age"]
email := m1["email"]
fmt.Printf("name: %v\n", name)
fmt.Printf("age: %v\n", age)
fmt.Printf("email: %v\n", email)
}

判断某个键是否存在

go语言中有个判断map中键是否存在的特殊写法,格式如下:

1
value, ok := map[key]

如果ok为 true,存在;否则,不存在。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import "fmt"

func main() {
m1 := make(map[string]string)
m1["name"] = "tom"
m1["age"] = "20"
m1["email"] = "[email protected]"

v, ok := m1["address"]
if ok {
fmt.Println("键存在")
fmt.Println(v)
} else {
fmt.Println("键不存在")
}
}

运行结果

1
键不存在

Go语言遍历map

可以使用 for range循环进行map遍历,得到key和value值。

遍历key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import "fmt"

func main() {
m := make(map[string]string)
m["name"] = "tom"
m["age"] = "20"
m["email"] = "[email protected]"

for key := range m{
fmt.Println(key)
}
}

运行结果

1
2
3
name
age
email

遍历key和value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import "fmt"

func main() {
m := make(map[string]string)
m["name"] = "tom"
m["age"] = "20"
m["email"] = "[email protected]"

for key, value := range m{
fmt.Println(key + ":" +value)
}
}

运行结果

1
2
3
name:tom
age:20
email:[email protected]