第12节 Go中的切片

196 阅读3分钟

1. 什么是切片

Go 语言切片是对数组的抽象,切片是数组的一个引用,数组是值类型,切片是引用类型,切片的长度是可以变化的,所以切片是一个可以动态变化的数组,可以理解成Java中的ArrayList

1.1 切片的定义语法

var 切片名称 []类型
示例:var a []int

注意:切面的声明和数组的声明稍微有点区别,切片声明时不知道具体的长度

2. 切片的创建方式

2.1 方式一

定义一个切片,然后让切片去引用一个已经创建好的数组

package main

import "fmt"

func main() {
	var arr [5]int = [...]int{1, 2, 3, 4, 5}
	// 声明一个切片,然后引用已经定义好的数组
	// 引用数组元素的区间是:前闭后开
	slice :=arr[1:3]
	// [2 3]
	fmt.Println(slice)
}

2.2 方式二

利用 make 来创建

func make

func make(Type, size IntegerType) Type
  • Type:指定数据类型
  • size:指定长度,默认该切片的容量等于其长度。切片支持第二个整数实参可用来指定不同的容量; 它必须不小于其长度,因此 make([]int, 0, 10) 会分配一个长度为0,容量为10的切片。
package main

import "fmt"

func main() {
	var sliceArr []int = make([]int, 5)
	sliceArr[0] = 1
	sliceArr[1] = 2
	// [1 2 0 0 0]
	fmt.Println(sliceArr)
}

2.3 方式三

定义一个切片,直接就指定具体的数组

package main

import "fmt"

func main() {
	var strSlice []string = []string{"A", "B", "C"}
        // [A B C]
	fmt.Println(strSlice)
}

3. 切片的遍历

  • for 循环遍历
  • for-range 遍历
package main

import "fmt"

func main() {
	var arrays [5]int = [...]int{1, 2, 3, 4, 5}
	// 声明一个切片,然后引用已经定义好的数组
	// 引用数组元素的区间是:前闭后开
	arr :=arrays[1:4]

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

	fmt.Println(arr)

	for i,v := range arr {
		fmt.Printf("i=%v, v=%v\n", i, v)
	}
}        

4. 切片使用细节

  • 切片初始化引用数组时,下标不能超过数组的最大长度,即var slice = [0 ~ len(array)],几种特殊情况的简写
var slice = arr[0:end] 简写为 var slice = arr[:end]
var slice = arr[start:len(arr)] 简写为 var slice = arr[start:]
var slice = arr[0:len(arr)] 简写为 var slice = arr[:]
  • 内置函数 capappendcopy函数的使用
    (1) func cap(v Type) int :返回切片中元素的数量


    (2) func append(slice []Type, elems ...Type) []Type :在切片中动态添加元素


package main

import "fmt"

func main() {

	var slice3 []int = []int{100, 200, 300}
	slice3 = append(slice3, 400, 500)
	// [100 200 300 400 500]
	fmt.Println(slice3)

	var arr3 []int = []int{600, 700}
	// [100 200 300 400 500 600 700],相当于 Java 中 ArrayList 的 addAll 方法
	slice3 = append(slice3, arr3...)
	fmt.Println(slice3)  
        
        var keys []int
	var arr6 [3]int = [3]int {1, 2, 3}
	for _,v := range arr6 {
		keys = append(keys, v)
	}
	// [1 2 3]
	fmt.Println(keys)
}

append 的本质是对数组进行扩容,将切片 slice3 指向扩容后的数组而已。 image.png


(3) func copy(dst, src []Type) int :对切片进行拷贝,会把 src 中数据复制到 dst 中,复制后的数是独立内存空间,互不影响。

package main

import "fmt"

func main() {
    var src []int = []int{1, 2, 3}
    var dst = make([]int, 1)
    copy(dst, src)
    // dst=[1], src=[1 2 3]
    fmt.Printf("dst=%v, src=%v\n",dst, src)
}

5. 字符串和切片

  • string底层是一个 byte 数组,所以 string 也可以用切片进行处理
package main

import "fmt"

func main() {
	str := "abcde@AAAAA"
	slice := str[6:]
	// slice= AAAAA
	fmt.Println("slice=", slice)
}
  • 字符串被初始化后不能被修改,如果要修改,可以采用如下方式
package main

import "fmt"

func main() {
	str := "abced@AAAAA"
	
	var b []rune = []rune(str)
	// b= [97 98 99 101 100 64 65 65 65 65 65]
	fmt.Println("b=", b)
	b[0] = 'A'
	str = string(b)
	// str= Abced@AAAAA
	fmt.Println("str=", str)
}

注意:这里推荐使用 []rune,因为 []byte无法处理中文