Go学习笔记(三)

187 阅读4分钟

(文章持续更新中...有志同道合的人可以一起探讨下。整个系列(1~8)准备重写,不过都是很基础的入门笔记,想学到很深入的东西则不建议阅读...)

复杂类型的变量称为容器

数组(Array)是一段固定长度的连续内存区域

数组申明 : var 数组变量名 [元素数量]T

var team [3]string
team[0] = "winyh"
team[1] = "snowman"
fmt.Println(team)

// 数组初始化
var team = [3]string{"winyh", "snowman", "age"}

// ...表示让编译器确定数组大小。编译器会自动为设置元素个数为 3
var team = [...]stringstring{"winyh", "snowman", "age"}

// 数组遍历
var team [3]string{"winyh", "snowman", "age"}

for k, v := range team {
    fmt.Println(k, v)
}

切片是一个拥有相同类型元素的可变长度的序列。一般用于快速地操作一块数据集合

从连续内存区域生成切片是常见的操作

slice 表示目标切片对象。
slice [开始位置:结束位置]
切片和数组密不可分

var a  = [3]int{1, 2, 3}
fmt.Println(a, a[1:2])

// 声明字符串切片
var strList []string
// 声明整型切片
var numList []int
// 声明一个空切片
var numListEmpty = []int{}

// 输出3个切片大小
fmt.Println(len(strList), len(numList), len(numListEmpty))
// 切片判定空的结果
fmt.Println(strList == nil)
fmt.Println(numList == nil)

使用 make() 函数构造切片

make( []T, size, cap )
T表示的元素类型
size表示为这个类型分配多少个元素
cap表示预分配的元素数量,不影响size,只是能提前分配空间,增强编译性能

内建函数 append() 可以为切片动态添加元素
numbers := []int
numbers = append(numbers, i)

var car []string
       
// 添加1个元素       
car = append(car, "OldDriver")
       
// 添加多个元素
car = append(car, "Ice", "Sniper", "Monk")
// 添加切片
team := []string{"Pig", "Flyingcake", "Chicken"}
car = append(car, team...)

// 切片复制
内建的 copy() 函数,可以迅速地将一个切片的数据复制到另外一个切片空间中
copy( destSlice, srcSlice []T) int
srcSlice 为数据来源切片
destSlice 为复制的目标。目标切片必须分配过空间且足够承载复制的元素个数。来源和目标的类型一致,copy 的返回值表示实际发生复制的元素个数

// 复制原始数据从4到6(不包含)
copy(copyData, srcData[4:6])

Go 语言中切片删除元素的本质是:以被删除元素为分界点,将前后两个部分的内存重新连接起来。
seq := []string{"a", "b", "c", "d", "e"}
// 指定删除位置       
index := 2
// 查看删除位置之前的元素和之后的元素
fmt.Println(seq[:index], seq[index+1:])
// 将删除点前后的元素连接起来
seq = append(seq[:index], seq[index+1:]...)
fmt.Println(seq)

Go语言map(Go语言映射)

在业务和算法中需要使用任意类型的关联关系时,就需要使用到映射,如学号和学生的对应、名字与档案的对应等

Go 语言中 map 的定义

map[KeyType]ValueType
KeyType为键类型
ValueType是键对应的值类型

map在申明时可以填充内容

m := map[string]string{
    "W": "forward",
    "A": "left",
    "D": "right",
    "S": "backward",
}

map 的遍历过程使用 for range 循环完成

scene := make(map[string]int)
scene["route"] = 66
scene["brazil"] = 4
scene["china"] = 960
for k, v := range scene {
    fmt.Println(k, v)
}

使用 delete() 内建函数从 map 中删除一组键值对

delete(map, 键) // map 是要删除的map实例

scene := make(map[string]int)
// 准备map数据
scene["route"] = 66
scene["brazil"] = 4
scene["china"] = 960
delete(scene, "brazil")

并发读写map时用async.map

package main
import (
      "fmt"
      "sync"
)
func main() {
    var scene sync.Map
    
    // 将键值对保存到sync.Map
    scene.Store("greece", 97)
    
    // 从sync.Map中根据键取值
    fmt.Println(scene.Load("greece"))
    
    // 根据键删除对应的键值对
    scene.Delete("greece")
    
    // 遍历所有sync.Map中的键值对
    scene.Range(func(k, v interface{}) bool {
        fmt.Println("iterate:", k, v)
        return true
    })
}

列表是一种非连续存储的容器,由多个节点组成,节点通过一些变量记录彼此之间的关系。列表有多种实现方法,如单链表、双链表等

有两种初始化列表的方法

通过 container/list 包的 New 方法初始化 list
变量名 := list.New()

var 变量名 list.List

双链表支持从队列前方或后方插入元素,分别对应的方法是 PushFront 和 PushBack.删除用Remove方法

遍历双链表需要配合 Front() 函数获取头元素,遍历时只要元素不为空就可以继续进行。每一次遍历调用元素的 Next

l := list.New()
// 尾部添加
l.PushBack("canon")
// 头部添加
l.PushFront(67)
for i := l.Front(); i != nil; i = i.Next() {
    fmt.Println(i.Value)
}