• Golang数组和slice


    Golang数组和Slice(切片)

    Go语言中数组长度固定不可变动,slice则可以增长缩短(使用较多)

    一、数组类型

    Go语言中数组长度固定, 索引从0开始计数。需要注意数组的长度一开始必须是固定的,且不同长度的数组其表示不同的数据类型,相同的数组可以进行 ‘==’ 比较。数组作为函数参数是使用的是形参的方式,函数内不可改变其值,需要使用数组指针的方式进行传值。

    1.数组初始化

    数组的长度可以写在 [ ] 中([10]int)或者使用 自动从 {1, 2, 3} 初始化参数中确定。数组的初始值默认为数组元素类型的零值

    package main
    
    import (
    	"fmt"
    )
    
    const (
    	a = iota
    	b
    	c
    	d
    )
    
    func main() {
    	//数组初始化
    	s := [3]int{1, 2, 3}
    	//索引对应的值
    	f := [...]string{a: "fht", b: "fyq", c: "zcy", d: "zcx"}
    	//长度为11,num[10]=-1,其余为‘0’
    	num := [...]int{10: -1}
    	fmt.Println(s)
    	fmt.Println(f)
    	fmt.Println(num)
    }
    // 输出
    //[1,2,3]
    // [fht fyq zcy zcx]
    // [0 0 0 0 0 0 0 0 0 0 -1]
    
    • 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

    2.数组相等判断

    两个类型相同,长度相同的数组可以相互判断是否相等。

    package main
    
    import (
    	"fmt"
    )
    func main() {
    	s := [3]int{1, 2, 3}
    	ss := [3]int{2, 3, 4}
    	if s == ss {
    		fmt.Println("s == ss")
    	} else {
    		fmt.Println("s != ss")
    	}
    }
    // 输出
    // s != ss
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.数组作为函数的传递参数

    不同于其他语言,Go语言的数组作为形参传递给函数,函数内部对数组的操作不影响外部数组。若要改变外部数组的值,需要传递数值指针的值。

    package main
    
    import (
    	"fmt"
    )
    func main() {
    	s := [3]int{1, 2, 3}
    	changeS1(s)
    	fmt.Println(s)
    	changeS2(&s)
    	fmt.Println(s)
    }
    
    //形参
    func changeS1(s [3]int) {
    	for i, _ := range s {
    		s[i] = 0
    		//fmt.Println(v)
    	}
    }
    
    //数组指针
    func changeS2(s *[3]int) {
    	for i, _ := range s {
    		s[i] = 0
    		//fmt.Println(v)
    	}
    }
    // 输出
    // [1 2 3]
    // [0 0 0]
    
    • 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

    二、slice类型

    Go语言的切片类型是常用的数据类型,该类型通过指针将数组扩展为可扩容的数据变量。slice三个属性:指针、长度和容量
    注意: 一个底层数组可以被多个切片使用,底层数组只有在没有被引用时才会进行GC,需要注意数组的及时释放,不然会造成内存浪费或者内存溢出。

    1、slice初始化

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
    	b := make([]int, 2, 5)
    	// b = a[:3]
    	b[0] = 1
    	b[1] = 2
    	fmt.Printf("len(a): %d\n%v\n", len(a), a)
    	fmt.Printf("len(b): %d\n%v\n", len(b), b)
    }
    
    // 输出
    // len(a): 9
    // [1 2 3 4 5 6 7 8 9]
    // len(b): 2
    // [1 2]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2、slice的引用

    若slice的引用超过了被引用对象的容量 cap(s) 则会宕机,但是若是超过的是其长度len(s) 则只会发生扩容。
    e.g

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
    	b := a[:4]
    	c := b[:7]
    	//d := a[:20]   会报错,超过了引用对象的cap
    	fmt.Printf("cap(a): %d\n", cap(a))
    	fmt.Printf("len(a): %d\n%v\n", len(a), a)
    	fmt.Printf("len(b): %d\n%v\n", len(b), b)
    	fmt.Printf("len(c): %d\n%v\n", len(c), c)
    }
    
    // 输出
    // cap(a): 9
    // len(a): 9
    // [1 2 3 4 5 6 7 8 9]
    // len(b): 4
    // [1 2 3 4]
    // len(c): 7
    // [1 2 3 4 5 6 7]
    
    • 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

    注:copy(dst, src)函数只会复制最小长度。

    3、append函数

    向切片末尾添加元素,需要注意该函数如果发生扩容则会改变切片指向的底层数组,故每次使用时需要对其重新赋值,例如s[ ], 使用:s = append(s, 1, 2, 3),执行函数之后s可能已经不是之前的s数组了,同理,当我们在调用函数时,如果改变了切片的容量,也需要重新赋值,不然其底层数组不会改变,则其值也不会变。

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    a := []int{1, 2, 3, 4, 5, 6}
    	fmt.Printf("cap(a): %d\n", cap(a))
    	fmt.Printf("len(a): %d\n%v\n", len(a), a)
    
    	testAppend1(a)
    	fmt.Printf("cap(a): %d\n", cap(a))
    	fmt.Printf("len(a): %d\n%v\n", len(a), a)
    
    	a = testAppend2(a)
    	fmt.Printf("cap(a): %d\n", cap(a))
    	fmt.Printf("len(a): %d\n%v\n", len(a), a)
    }
    //该函数无法没有返回扩容之后的数组,故原切片不会变化
    func testAppend1(a []int) {
    	a = append(a, 1, 2, 3, 4)
    }
    //该函数更新了扩容之后的数组,故原切片发生变化
    func testAppend2(a []int) []int {
    	a = append(a, 7, 8, 9)
    	return a
    }
    // 输出
    // cap(a): 6
    // len(a): 6
    // [1 2 3 4 5 6]
    // cap(a): 6
    // len(a): 6
    // [1 2 3 4 5 6]
    // cap(a): 12
    // len(a): 9
    // [1 2 3 4 5 6 7 8 9]
    
    • 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
    • 37
    • 38

    4、slice就地修改

    避免重新分配数组。
    e.g.
    编写函数,去除[ ]string 中相邻的重复字符串元素。

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	str := []string{"123", "456", "456", "789"}
    	str = delsimple(str)
    	fmt.Println(str)
    }
    
    func delsimple(s []string) []string {
    	var p int = 1
    	lent := len(s)
    	for i := 1; i < lent; i++ {
    		if s[i] != s[i-1] {
    			s[p] = s[i]
    			p++
    		}
    	}
    	return s[:p]
    }
    // 输出
    // [123 456 789]
    
    • 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
  • 相关阅读:
    内存对齐对性能的影响
    Docker部署Emqx并配置ssl支持微信小程序
    FANUC机器人Process IO接线及信号配置方法(一)
    Malformed \uxxxx encoding解决总结
    react中遇到的分页问题
    后端研发工程师面经——计算机网络
    PaddleOCR训练部署文档
    vite2 + vue3 使用svg图标
    Kafka-Java一:Spring实现kafka消息的简单发送
    <C++> STL_set/map
  • 原文地址:https://blog.csdn.net/fuhaitao9999/article/details/132869022