10-Golang复合数据类型---slice(切片)

切片是长度可变的数组(具有相同数据类型的数据项组成的一组长度可变的序列),切片由三部分组成:
指针:指向切片第一个元素指向的数组元素的地址
长度:切片元素的数量
容量:切片开始到结束位置元素的数量

切片声明需要指定组成元素的类型,但不需要指定存储元素的数量(长度)。在切片声明后,会被初始化为nil,表示暂不存在的切片。

定义切片

//定义切片
var identifier []type

//使用 make() 函数来创建切片:
var slice1 []type = make([]type, len)

//也可以简写为
slice1 := make([]type, len)

//也可以指定容量,其中 capacity为可选参数。
make([]T, length, capacity)  //这里 len 是数组的长度并且也是切片的初始长度。

初始化切片

s := []int{1,2,3} //直接使用字面量初始化切片,[]表示是切片类型,{1,2,3} 初始化值依次是 1,2,3,其 cap=len=3。

s := []int{}  //使用字面量初始化空切片

s := []int{1:1, 3:3, 99:99} //指定长度和容量字面量初始化

s := arr[:]   //初始化切片s,是数组arr的引用。

s := arr[startIndex:endIndex]  //将arr中从下标startIndex到endIndex-1下的元素创建为一个新的切片。

s := arr[startIndex:endIndex:cap]        //注意end<=cap<=len

s := arr[startIndex:]   //默认endIndex时将表示一直到arr的最后一个元素。

s := arr[:endIndex]     //默认startIndex时将表示从arr的第一个元素开始。

s1 := s[startIndex:endIndex] //通过切片s初始化切片s1。

s := make([]int,len,cap) //通过make函数创建长度为len,容量为cap的切片,len必须小于等于cap。cap可以省略。

len() 和 cap() 函数

切片是可索引的,可以使用len()函数可获取切片的长度,使用cap()函数可获取切片容量

空(nil)切片 一个切片在未初始化之前默认为 nil,长度为 0。

package main

import "fmt"

func printSlice(x []int) {
    fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}

func main() {
    var s []int
    if s == nil {
        fmt.Printf("切片是空的\n")
    }

    var numbers = make([]int, 3, 5)
    printSlice(numbers)
}

切片截取

可以通过设置下限及上限来设置截取切片 [lower-bound:upper-bound]

package main

import "fmt"

func printSlice(x []int) {
    fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}

func main() {
    /* 创建切片 */
    numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
    printSlice(numbers)

    /* 打印原始切片 */
    fmt.Println("numbers ==", numbers)

    /* 打印子切片从索引1(包含) 到索引4(不包含)*/
    fmt.Println("numbers[1:4] ==", numbers[1:4])

    /* 默认下限为 0*/
    fmt.Println("numbers[:3] ==", numbers[:3])

    /* 默认上限为 len(s)*/
    fmt.Println("numbers[4:] ==", numbers[4:])

    numbers1 := make([]int, 0, 5)
    printSlice(numbers1)

    /* 打印子切片从索引  0(包含) 到索引 2(不包含) */
    number2 := numbers[:2]
    printSlice(number2)

    /* 打印子切片从索引 2(包含) 到索引 5(不包含) */
    number3 := numbers[2:5]
    printSlice(number3)

}

append() 和 copy() 函数

如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。

package main

import "fmt"

func main() {
    var numbers []int
    printSlice(numbers)

    /* 允许追加空切片 */
    numbers = append(numbers, 0)
    printSlice(numbers)

    /* 向切片添加一个元素 */
    numbers = append(numbers, 1)
    printSlice(numbers)

    /* 同时添加多个元素 */
    numbers = append(numbers, 2, 3, 4)
    printSlice(numbers)

    /* 创建切片 numbers1 是之前切片的两倍容量*/
    numbers1 := make([]int, len(numbers), (cap(numbers))*2)

    /* 拷贝 numbers 的内容到 numbers1 */
    copy(numbers1, numbers)
    printSlice(numbers1)
}

func printSlice(x []int) {
    fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}

练习:

package main

import "fmt"

func main() {
    //切片: 长度可变的数组
    /*
        切片由三部分组成:
            指针: 指向切片第一个元素指向的数组元素的地址
            长度: 切片元素的数量
            容量: 切片开始到结束位置元素的数量
    */

    //切片声明需要指定组成元素的类型,但不需要指定存储元素的数量(长度)。
    //切片声明后,会被初始化为nil,表示暂不存在的切片

    var sliceint []int
    fmt.Printf("%T %t %v\n", sliceint, sliceint == nil, sliceint)
    fmt.Printf("%#v %d %d\n", sliceint, len(sliceint), cap(sliceint))

    //字面量
    sliceint = []int{1, 2, 3}
    fmt.Printf("%#v %d %d\n", sliceint, len(sliceint), cap(sliceint))
    fmt.Println(sliceint)
    sliceint = []int{1, 2, 3, 4}
    fmt.Printf("%#v %d %d\n", sliceint, len(sliceint), cap(sliceint))
    fmt.Println(sliceint)

    // 通过数组切片赋值
    var arrayint [10]int = [10]int{1, 2, 3, 4, 5, 6}
    sliceint = arrayint[1:10]
    fmt.Printf("%#v %d %d\n", sliceint, len(sliceint), cap(sliceint))
    fmt.Println(sliceint)

    //获取切片的长度 len()
    //获取切片的容量 cap()
    fmt.Printf("%#v %d %d\n", sliceint, len(sliceint), cap(sliceint))

    //make函数 会对指针进行初始化
    sliceint = make([]int, 3)
    fmt.Printf("%#v %d %d\n", sliceint, len(sliceint), cap(sliceint))

    sliceint = make([]int, 3, 5)
    fmt.Printf("%#v %d %d\n", sliceint, len(sliceint), cap(sliceint))

    //元素操作(增删改查)
    fmt.Println(sliceint[0])
    fmt.Println(sliceint[1])
    fmt.Println(sliceint[2])
    //fmt.Println(sliceint[3])
    //fmt.Println(sliceint[4])
    sliceint[2] = 10
    fmt.Println(sliceint)
    sliceint = append(sliceint, 3)
    fmt.Println(sliceint)

    for i := 0; i <= len(sliceint)-1; i++ {
        fmt.Println(sliceint[i])
    }
    for i, v := range sliceint {
        fmt.Println(i, v)
    }

    //切片操作
    fmt.Printf("%T %v\n", sliceint[1:5], sliceint[1:5])
    sliceint = make([]int, 3, 10)
    fmt.Printf("%T %d %d\n", sliceint, len(sliceint), cap(sliceint))
    //s_cap - start
    //len - start
    s := sliceint[1:3:9]
    fmt.Printf("%T %d %d\n", s, len(s), cap(s))
    //src_cap - start
    s1 := sliceint[4:6]
    fmt.Printf("%T %d %d\n", s1, len(s1), cap(s1))

    //切片的切片,底层是共用指针地址
    sliceint = make([]int, 3, 5)
    sliceint2 := sliceint[1:3]
    fmt.Println(sliceint, sliceint2)

    sliceint2[0] = 1
    fmt.Println(sliceint, sliceint2)

    sliceint2 = append(sliceint2, 4)
    fmt.Println(sliceint, sliceint2)

    sliceint = append(sliceint, 5)
    fmt.Println(sliceint, sliceint2)

    sliceint = arrayint[:]
    fmt.Println(sliceint, arrayint)

    sliceint[0] = 100
    fmt.Println(sliceint, arrayint)

    //删除
    //copy
    sliceint001 := []int{1, 2, 3}
    sliceint002 := []int{10, 20, 30, 40}
    copy(sliceint002, sliceint001)
    fmt.Println(sliceint001, sliceint002)

    sliceint002 = []int{10, 20, 30, 40}
    copy(sliceint001, sliceint002)
    fmt.Println(sliceint001, sliceint002)

    //删除索引为0,索引1
    sliceint003 := []int{1, 2, 3, 4, 5}
    fmt.Println(sliceint003[1:])
    fmt.Println(sliceint003[:len(sliceint003)-1])

    //删除中间的元素2(3)
    copy(sliceint003[2:], sliceint003[3:])
    fmt.Println(sliceint003[:len(sliceint003)-1])

    //堆栈,队列
    //队列: 每次添加在队尾,移除元素在队头
    //堆栈: 每次添加在队尾,移除元素在队尾

    //队列
    queue := []int{}
    queue = append(queue, 1)
    queue = append(queue, 2)
    queue = append(queue, 3)
    queue = append(queue, 4)
    //1,2,3,4
    fmt.Println(queue)
    //2,3,4
    queue = queue[1:]
    fmt.Println(queue)
    //3,4
    queue = queue[1:]
    fmt.Println(queue)

    //堆栈
    stack := []int{}
    stack = append(stack, 1)
    stack = append(stack, 2)
    stack = append(stack, 3)
    stack = append(stack, 4)
    //1,2,3,4
    fmt.Println(stack)
    //1,2,3
    stack = stack[:len(stack)-1]
    fmt.Println(stack)
    //1,2
    stack = stack[:len(stack)-1]
    fmt.Println(stack)
}

多维切片

package main

import "fmt"

func main() {
    //定义多维切片
    var mslice [][]int
    //mslice := make([][]int, 0)
    mslice = append(mslice, []int{1, 2, 3})
    mslice = append(mslice, []int{3, 4, 0})
    fmt.Println(mslice)
    //切片的切片操作
    fmt.Println(mslice[0])
    fmt.Println(mslice[0][1])
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容