Lxn-Chan!

江泽民同志永垂不朽!

我自己的Go语言学习笔记。

仓库地址

LxnChan/go-learn

Go语言总体结构

每个Go语言项目应至少包含main.gogo.mod文件,前者是入口文件,后者是项目名称、所使用Go版本和需要引入的模块的列表。

main.go应由最少两个结构:包名和main函数组成:

1
2
3
4
5
package main

func main() {

}

可以使用import关键字引入包:

1
2
3
4
5
6
7
package main

import "fmt"

func main() {
fmt.Println("Hello world.")
}

其中函数结构体的花括号不能单独一行,必须和func等关键字处于同一行。

所有逻辑必须在函数内部。

变量、常量和赋值

变量

1
2
3
4
5
6
7
8
// 由三部分组成:var 变量名 数据类型
var name string

// 也可以在定义变量时赋值
var name string = "XiaoMing"

// 不写数据类型可以让编译器自行推导类型
var name = "XiaoMing"

如果变量从未被引用过则编译器可能会报错;

不能同时不写数据类型又不赋值。

也可以在函数中短定义变量,基本结构变量名:=值

1
2
3
4
5
6
7
8
9
package main

import "fmt"

func main() {
if nbhl := 999; nbhl < 5 {
fmt.Println("not true")
}
}

常量

1
2
// 基本和变量的方法是一样的
const name2 string

运算符

算术运算

+-*/

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

import "fmt"

func main() {
//算术运算符
var a int = 10
var b int = 90
fmt.Println(a + b)
fmt.Println(a - b)
fmt.Println(a * b)
fmt.Println(a / b)
}

除四则运算还有一个取余数:

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

import "fmt"

func main() {
//算术运算符
var a int = 5
var b int = 2
fmt.Println(a % b)
}

输出结果是1

自增自减

  • ++:自增,步进值为1;
  • --:自减,步进值为1。

比较(关系运算)

  • >/>=:大于和大于等于;
  • </<=:小于和小于等于;
  • !=/==:不等于和等于;

逻辑运算

下表列出了所有Go语言的逻辑运算符。假定 A 值为 True,B 值为 False。

  • &&:逻辑 AND 运算符:如果两边的操作数都是 True,则条件 True,否则为 False,(A && B) 为 False;
  • ||:逻辑 OR 运算符:如果两边的操作数有一个 True,则条件 True,否则为 False,(A || B) 为 True;
  • !:逻辑 NOT 运算符。如果条件为 True,则逻辑 NOT 条件 False,否则为 True,!(A && B) 为 True。

流程控制

If

基本结构:

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() {
if 条件表达式 {
语句
} else if 条件表达式 {
语句
} else {
语句
}
// 示例
if nbhl := 999; nbhl < 5 {
fmt.Println("not true")
} else {
fmt.Println("666")
}
}

If 语句可以简写为:

1
2
3
4
5
// if简写
var a bool=true
if a {
fmt.Println("True.")
}

=true部分可忽略。

For

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

import "fmt"

func main() {
// 变量;条件;步进{语句}
for i:=0; i<5; i++ {
fmt.Println(i)
}
}

break跳出循环

执行到break时立即停止。

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

import "fmt"

func main() {
//break跳出循环
var c int
for {
c++
fmt.Println(c)
if c == 100 {
break
}
}
}

Switch

1
2
3
4
5
6
7
8
9
10
11
switch 变量 {
case1:
语句
case2:
语句
case3, 值4, 值5:
语句
//只能有一个default语句,如果其他都不符合则落入default中
default:
语句
}

延迟执行

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

import "fmt"

//defer:延迟执行,先被defer的语句最后被执行
//等整个函数即将结束但还未结束时逆序执行
func main() {
fmt.Println("Start...") //
defer fmt.Println("1") // 执行至此时将defer语句依次沉入池子底部,待函数内全部语句执行结束后再倒序执行(从池子最上端开始执行)
defer fmt.Println("2") // defer适用于执行后清理和记录时间、日志等情况。
defer fmt.Println("3")
fmt.Println("end")
}

数组

定义方法:

1
2
3
4
5
6
7
8
9
// var 数组名 = [数量] 类型 {元素0,...,元素n-1}
var arrCity = [2] string {"Beijing", "Tianjin"}
// 让编译器自行判断元素数量
var arrPoint = [...] int {99, 98, 99, 100, 92}
// 索引值方式
var arrPeople = [...]string{1: "小王", 3: "18", 7: "女"}
fmt.Println("姓名为", arrPeople[1], ",年龄为", arrPeople[3], ",性别为", arrPeople[7])
// 获取数组长度,下例返回值应为5
fmt.Println(len(arrPoint))

多维数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 多维数组
// 数组嵌套数组,注意元素数量,里面嵌套几层就写几个
// 注意只有第一层可以使用[...]让编译器推导
var arrRobot = [...][4]string{
{"1a96", "2a13", "3a16", "4a19"},
{"1a96b", "2a13b", "3a16b", "4a19b"},
}
fmt.Println(arrRobot[1][2])
// 多维遍历
for i := 0; i <= len(arrRobot)-1; i++ {
fmt.Println(i)
for j := 0; j <= 3; j++ {
fmt.Println(j)
fmt.Println(arrRobot[i][j])
}
}

获取多维数组元素数量

给定数组,求获取{7, 3, 6}的元素数量。

1
2
3
4
var arrTmp = [][]int{{1, 5}, {7, 3, 6}, {3, 5}}

len(arrTmp[1])
// 输出:3

切片

切片的底层本质就是一种数组。

1
2
// var 数组名 = [] 类型 {元素0,...,元素n-1}
var sliceAtr = [] int {9, 6, 6}

基于数组得到切片

数组或切片的截取操作。截取操作有带 2 个或者 3 个参数,形如:[i:j][i:j:k],假设截取对象的底层数组长度为 l。在操作符 [i:j] 中,如果 i 省略,默认 0,如果 j 省略,默认底层数组的长度,截取得到的切片长度和容量计算方法是 j-il-i。操作符 [i:j:k],k 主要是用来限制切片的容量,但是不能大于数组的长度 l,截取得到的切片长度和容量计算方法是 j-ik-i

1
2
3
4
// 从数组获得切片
var arrNtr = [...]string{"Natsuki", "Torari", "Klier"}
sliceNtr := arrNtr[0:3]
fmt.Println(sliceNtr)

Make函数构造切片

1
2
3
4
// make函数构造切片
// make([]类型,元素数量,容量)
var sliceMrr = make([]int, 5, 10)
fmt.Println(sliceMrr)

元素数量是指里面会被初始化进去多少个元素,容量则是指底层数组的最大容量。容量值可省略,省略时容量=元素数量。

上例中输出值应为[0 0 0 0 0],因为初始化进去了五个元素,都是对应类型的默认值。

Map(映射)

  1. 声明Map并初始化

    其中键值对数量可以省略。

    1
    2
    3
    4
    5
    6
    // var 映射名 = make(map[Key数据类型]值数据类型, 键值对数量)
    var mapCity = make(map[string]string, 8)
    fmt.Println(mapCity)
    mapCity["Beijing"] = "001"
    mapCity["Shanghai"] = "002"
    fmt.Println(mapCity)
  2. 取出键值

    1
    fmt.Println(mapCity["Shanghai"])
  3. 判断键值是否存在

    1
    2
    3
    4
    // val为若存在则取出的值,否则val为该类型的默认值
    // ok是约定俗成的写法,代表该值是否存在,可以使用if ok {}这样的语句来判断
    val, ok := mapCity["ShenYang"]
    fmt.Println(ok, val)

Map 遍历

使用for...range...结构来遍历map:

1
2
3
4
// 第一个和第二个变量分别是关键字(Key)和值(Value)
for k, v := range mapCity {
fmt.Println(k, v)
}

如果不需要接收其中一个值可以这么写:

1
2
3
4
5
6
7
// 如果需要忽略的值在第二位可以不写
for k, _ := range mapCity {
fmt.Println(k, v)
}
for _, v := range mapCity {
fmt.Println(k, v)
}

获取切片容量

1
cap()

Map 排序

待完成。

指针

Go语言中指针只有两种操作:取地址(&)和根据地址取值(*)。

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

import "fmt"

func main() {
a := 666
// 取a的地址
b := &a
// 获取b地址所对应的值
fmt.Println(b, *b)
}

在上例中,a的类型为int,则b(指针)的类型为*int

指针传值

可以通过指针传值修改变量值。

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

import "fmt"

func main() {
var c int = 996
modify1(c)
// 此时c的值没有被改变
fmt.Println(c)
modify2(&c)
// 此时c的值被改变
fmt.Println(c)
}

func modify1(x int) {
x = 955
return
}

func modify2(y *int) {
*y = 1055
return
}

 简单说两句



联系站长 | 安装证书 | 友情链接

备案号:辽ICP备19013963号

萌ICP备 20219421 号

中国互联网违法和不良信息举报中心

架构版本号:8.1.0 | 本站已全面支持IPv6

本站由又拍云提供CDN加速服务和存储服务

正在载入运行数据(1/2)请稍后...
正在载入运行数据(2/2)请稍后...

Copyright 2022 LingXuanNing, All rights reserved.