• Go 数组(array) & 切片(slice)


    数组

    数组是一组固定长度的序列

    数组类型

    数组的类型不仅和储存元素的类型有关,还和数组长度有关,不同长度的数组是不同的类型
    不同类型的数组不能共用一个函数

    func main() {
    	var a [10]int
    	var b [5]int
    	var c [5]int32
    	fmt.Printf("type a: %T,
    type b: %T,
    type c: %T", a, b, c)
    }
    

    储存数据

    由于数组中储存的是值,所以直接传入函数中无法改变原来的值,需要传入地址才能修改原来的值

    传值

    示例:

    func change(a [5]int){
    	fmt.Println("in change, before change", a)
    	a[0] = 100
    	fmt.Println("in change, after change", a)
    }
    
    func toChange() {
    	a := [5]int{0, 0, 0, 0, 0}
    	fmt.Println("in main, before change", a)
    	change(a)
    	fmt.Println("in main. after change", a)
    }
    

    输出结果:

    in main, before change [0 0 0 0 0]
    in change, before change [0 0 0 0 0]
    in change, after change [100 0 0 0 0]
    in main. after change [0 0 0 0 0]
    

    main 中数组并没有改变

    传引用

    示例:

    func change(a *[5]int){
    	fmt.Println("in change, before change", *a)
    	a[0] = 100
    	fmt.Println("in change, after change", *a)
    }
    
    func main() {
    	a := [5]int{0, 0, 0, 0, 0}
    	fmt.Println("in main, before change", a)
    	change(&a)
    	fmt.Println("in main. after change", a)
    }
    

    输出结果:

    in main, before change [0 0 0 0 0]
    in change, before change [0 0 0 0 0]
    in change, after change [100 0 0 0 0]
    in main. after change [100 0 0 0 0]
    

    main 中数组发生改变

    数组初始化

    在数组未进行初始化时,所有的元素都是默认值

    // 标准初始化
    var array [5]int = [5]int{1, 2, 3, 4, 5}
    
    // 省略类型,会自动判断数组长度与元素类型
    var array = [5]int{1, 2, 3, 4, 5}
    
    // 省略长度,会自动判断初始化元素个数来确定长度
    var array = [...]int{1, 2, 3, 4, 5}
    
    // 指定索引初始化
    var array = [5]int{0: 3, 4: 3}
    

    切片

    切片时数组的一个引用,是引用类型
    切片长度可变

    切片的结构

    切片内部储存的只有指向相应数组对应元素的指针和切片的长度、容量

    package main
    
    import "fmt"
    
    func main() {
    	var array = [5]int{1, 2, 3, 4, 5}
    	var slice = array[2:]
    	fmt.Printf("array: %p slice: %p
    ", &array[2], slice)
    }
    
    

    输出结果:

    array: 0xc00001a160 slice: 0xc00001a160
    

    切片从 array[2] 开始,所以指向的就是 array[2]

    切片定义

    var slice[]int

    切片初始化

    切片初始化的时候可以自己创建一个数组进行初始化,也可以用 make 进行初始化,但是 make 实际上也是创建了一个数组,切片的数据都存在这个数组里,切片改变数组里的值也会改变

    // 通过数组初始化
    var slice[]int = array[start: end]
    
    // 通过 make 初始化,第一个参数为类型,第二个参数为长度,第三个参数为数组长度,默认等于切片长度
    var slice = make([]int, len)
    var slice = make([]int, len, cap)
    

    二维切片初始化

    二维切片外层直接初始化,但是内层需要循环每个外层切片进行初始化

    slice := make([][]int, height)
    for i := range slice {
    	slice[i] = make([]int, width)
    }
    

    append

    append 用于在切片后面添加元素

    用法

    // 切片后添加元素
    slice = append(slice, elems)
    
    // 切片后添加切片
    // slice... 用来将 slice 展开
    slice = append(slice, slice...)	
    

    实现

    由于切片是基于数组的,但是数组的长度不可变,所以进行 append 操作时,
    如果内存空间不足:切片会新开辟一段内存空间由于存储新数组,每次开辟都是原来数组长度的两倍
    如果内存空间够用:切片会使用原来数组的内存,修改数组中原来的元素

    开辟空间示例:

    func main() {
    	var array = [10]int{}
    	var slice = array[:]
    	fmt.Printf("slice %p len: %d
    ", slice, len(slice))
    	slice = append(slice, 2)
    	fmt.Printf("slice %p len: %d(should change)
    ", slice, len(slice))
    	slice = append(slice, slice[:len(slice) - 2]...)
    	fmt.Printf("slice %p len: %d(should not change)
    ", slice, len(slice))
    	slice = append(slice, 1)
    	fmt.Printf("slice %p len: %d(should change)
    ", slice, len(slice))
    }
    

    输出结果:

    slice 0xc00001e050 len: 10
    slice 0xc0000140a0 len: 11(should change)
    slice 0xc0000140a0 len: 20(should not change)
    slice 0xc00008c000 len: 21(should change)
    

    初始数组长度为 10,
    append 1 个元素之后,长度为 11,由于超过数组最大长度,所以需要开辟新的内存空间,长度为 20,切片指向的地址发生改变
    append 9 个元素之后,长度为 20,由于没有超过数组最大长度,所以指向不变
    append 1 个元素之后,长度为 21,由于超过数组最大长度,所以需要开辟新的内存空间,长度为 40,切片指向的地址发生改变

    修改数组示例:

    func main() {
    	var array = [10]int{8: 1}
    	var slice = array[: 8]
    	fmt.Printf("slice %p len: %d
    ", slice, len(slice))
    	fmt.Printf("array: %v
    ", array)
    	slice = append(slice, 2)
    	fmt.Printf("slice %p len: %d(should not change)
    ", slice, len(slice))
    	fmt.Printf("array: %v
    ", array)
    	slice = append(slice, 2)
    	fmt.Printf("slice %p len: %d(should not change)
    ", slice, len(slice))
    	fmt.Printf("array: %v
    ", array)
    	slice = append(slice, 2)
    	fmt.Printf("slice %p len: %d(should change)
    ", slice, len(slice))
    	fmt.Printf("array: %v
    ", array)
    }
    

    输出结果:

    slice 0xc00001e050 len: 8
    array: [0 0 0 0 0 0 0 0 1 0]
    slice 0xc00001e050 len: 9(should not change)
    array: [0 0 0 0 0 0 0 0 2 0]
    slice 0xc00001e050 len: 10(should not change)
    array: [0 0 0 0 0 0 0 0 2 2]
    slice 0xc0000140a0 len: 11(should change)
    array: [0 0 0 0 0 0 0 0 2 2]
    

    初始数组长度为 10,但是切片切了前 8 个元素
    append 的元素未超过数组本身的长度时,会直接修改数组中原来的元素,如果超过了,则开辟新的内存

    copy

    copy 用来复制切片
    如果被复制的切片元素不足,多余部分不变
    如果被复制的切片元素超出目标切片长度(与容量无关),则忽略超出部分
    用法:

    // 切片 dst 变为 切片 scr 的复制
    copy(dst []Type, src []Type)
    

    示例:

    func main(){
    	a := []int{1, 2, 3, 4, 5}
    	b := make([]int, 3, 4)
    	fmt.Printf("b: %v, a: %v
    ", b, a)
    	copy(b, a)
    	fmt.Printf("b: %v, cap: %d, prt: %p
    ", b, cap(b), b)
    	b = append(b, 1)
    	fmt.Printf("b: %v, cap: %d, prt: %p
    ", b, cap(b), b)
    	copy(b, a)
    	fmt.Printf("b: %v, a: %v
    ", b, a)
    }
    

    输出结果:

    b: [0 0 0], a: [1 2 3 4 5]
    b: [1 2 3], cap: 4, prt: 0xc000018140
    b: [1 2 3 1], cap: 4, prt: 0xc000018140
    b: [1 2 3 4], a: [1 2 3 4 5]
    

    string

    字符串 (string) 就是 bytes 组成的不可变的集合
    关于字符串类型 <- 点击查看

  • 相关阅读:
    HiperLink
    三次贝塞尔曲线平滑多边形
    SimpleIni
    Segment
    SegIntersect
    OneTif
    OneSeg
    MiniDump
    MfcStrFile
    vmware workstation 如何配置NAT
  • 原文地址:https://www.cnblogs.com/dbf-/p/12074933.html
Copyright © 2020-2023  润新知