go之切片

定义

  切片是由数组建立的一种方便、灵活且功能强大的包装,切片本身不拥有任何数据。他们只是对现有数组的引用。切片底层以来于数组,是对数组的引用

  底层数组如果发生变化,切片也变了;切片发生变化,层数组也变化

切片定义

  基于数组生成切片

1
2
3
4
5
6
7
8
9
10
11
package main
 
import "fmt"
 
func main() {
    var a [10]int
    var s = a[:]
    fmt.Println(s)
 
}
//[0 0 0 0 0 0 0 0 0 0]

  注意点

1
2
3
4
5
6
7
8
9
10
package main
 
import "fmt"
 
func main() {
    var a [10]int
    //var s = a[:]  // 把数组从第0个位置切到最后一个位置,赋值给s切片
    var s []int=a[:]  // 中括号中只要不放任何东西就是切片,放了数字就是数组
    fmt.Println(s)
}

切片定义并初始化

  切片只定义不初始化,默认0值为nil

  通过make初始化

1
2
3
4
5
6
7
8
9
package main
 
import "fmt"
 
func main() {
    var s []int=make([]int,3,4)
    fmt.Println(s)
}
//[0 0 0]

  直接定义并初始化

1
2
3
4
5
6
7
8
9
package main
 
import "fmt"
 
func main() {
    var s []int=[]int{3,4,5}
    fmt.Println(s)
}
//[3 4 5]

切片追加元素

  数组不允许追加元素,切片可以

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
39
package main
 
import "fmt"
 
func main() {
    var a [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    var b []int = a[7:8]
    //b[0]=999
    //fmt.Println(a)  //[1 2 3 4 5 6 7 999 9 10]
    //fmt.Println(b)  //[999]
 
 
    b = append(b, 888)
    fmt.Println("切片b:", b) //切片b: [8 888]
    fmt.Println("数组a:", a) //数组a: [1 2 3 4 5 6 7 8 888 10]
    fmt.Println(len(b))    //切片长度是2
    fmt.Println(cap(b))    //切片容量是3
 
 
    b = append(b, 777)
    fmt.Println("切片b:", b) //切片b: [8 888 777]
    fmt.Println("数组a:", a) //数组a: [1 2 3 4 5 6 7 8 888 777]
    fmt.Println(len(b))    //切片长度是3
    fmt.Println(cap(b))    //切片容量是3
 
    //现在长度是3,容量是3,如果再追加666的话久超过了底层数组大小
    //如果超过底层数组大小:1.重新申请一个底层数据,把切片的值copy过去,2.切片的容量变为原来切片容量的两倍,3.现在这个切片跟原来的数组久没有关系了
    b=append(b,666)
    fmt.Println("切片b:",b)  //切片b: [8 888 777 666]
    fmt.Println("数组a:",a)  //数组a: [1 2 3 4 5 6 7 8 888 777]
    fmt.Println(len(b))  //切片长度是4
    fmt.Println(cap(b))  //切片长度是6
 
    //修改切片,不会影响最原来的数组
    b[0]=9
    a[9]=7
    fmt.Println("切片b:",b)  //切片b: [9 888 777 666]
    fmt.Println("数组a:",a)  //数组a: [1 2 3 4 5 6 7 8 888 7]
}

make创建切片

1
2
3
4
5
6
7
8
import "fmt"
 
func main() {
    var s =make([]int,3,4)
    fmt.Println(s)  //[0 0 0]
    fmt.Println(len(s))  //3
    fmt.Println(cap(s))  //4
}

切片的零值

  切片的零值为:nil

1
2
3
4
5
6
7
8
9
10
11
import "fmt"
 
func main() {
    var s []int=make([]int,2,2)  // 定义,有初始化
    fmt.Println(s[0])  //0
    if s==nil{
        fmt.Println("我是nil")
    }else {
        fmt.Println("我不是nil"//我不是nil
    }
}
1
2
3
4
5
6
7
8
9
10
11
import "fmt"
 
func main() {
    var s []int  // 只定义,没有初始化
    fmt.Println(s)  //[]
    if s==nil{
        fmt.Println("我是nil"//我是nil
    }else {
        fmt.Println("我不是nil"
    }
}

切片的参数传递

  切片是引用类型,当参数传递在函数中修改会影响原来的

  go语言的参数传递都是copy传递,因为切片是个引用(地址,指针),把切片复制了一份传入了。

  由于切片是引用,在函数中根据引用改了值,改了原来的底层数组,大家都会手影响

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main
 
import "fmt"
 
func main() {
    var s []int=[]int{3,4,5}
    testS(s)
    fmt.Println("调用之后:",s)  //调用之后: [999 4 5]
}
 
func testS(s []int)  {  // 在函数中追加切片,一定要注意有没有超过容量,如果超过了容量,超过后再改的值,就不会影响原来的了
    fmt.Println(s)   //[3 4 5]
    s[0]=999  //[999 3 5]
    s=append(s,888,777)  //[999 4 5 888 777]
    s[1]=666  //[999 666 5 888 777]
    fmt.Println(s)  // [999 666 5 888 777]
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main
 
import "fmt"
 
func main() {
    var s []int = make([]int, 3, 4)
    testS(s)
    fmt.Println("调用之后:", s) //调用之后: [999 0 0]
}
func testS(s []int) { // 在函数中追加切片,一定要注意有没有超过容量,如果超过了容量,超过后再改的值,就不会影响原来的了
    fmt.Println(s)          //[0 0 0]
    s[0] = 999              //[999 0 0]  会影响原来的
    s = append(s, 888, 777) //[999 0 0 888 777],追加了超过了底层数组,不依赖于原来的数组了
    s[1] = 666              //[999 666 0 888 777]  // 不影响原来的数组了
    fmt.Println(s)          // [999 666 0 888 777]
}

copy切片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main
 
import "fmt"
 
func main() {
    var a [100000]int
    var b =a[:3]
    fmt.Println(b)  //[0 0 0]
    b[0]=999
    b[2]=222
    fmt.Println(b)  //[999 0 222]  使用b,虽然只用3个值,但是底层数组很大,内存占用大
    //把b这个切片,copy另一个新切片上
    var c= make([]int,2,2)  // 基于的底层数组,数组大小是3
    copy(c,b)
    fmt.Println(c)  //[999 0]
}

多维切片

  每一层都要初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
import "fmt"
 
func main() {
    //var s [][]int=make([][]int,2,2)
    //var s [][]int
    //fmt.Println(s[0])  //[]
    //fmt.Println(s[0][0])  // 报错,第二层没有初始化
 
    // 循环切片  两层for循环,跟数组一样
    var s [][]int=[][]int{{2,3},{4,4,4,5},{6,7,8}}
    fmt.Println(s)  //[[2 3] [4 4 4 5] [6 7 8]]
    fmt.Println(s[0][1])  //3
}

  切片的底层实现 

  切片和数组的修改都会相互影响

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main
 
import "fmt"
 
func main() {
    var a [10]int=[10]int{1,2,3,4,5,6,7,8,9,10}
    var b []int=a[:]
    fmt.Println("数组a:",a)  //数组a: [1 2 3 4 5 6 7 8 9 10]
    fmt.Println("切片b:",b)  //切片b: [1 2 3 4 5 6 7 8 9 10]
 
    a[0]=999
    fmt.Println("数组a:",a)  //数组a: [999 2 3 4 5 6 7 8 9 10]
    fmt.Println("切片b:",b) // 也改了,影响了  切片b: [999 2 3 4 5 6 7 8 9 10]
    b[1]=888
    fmt.Println("数组a:",a)  //数组a: [999 888 3 4 5 6 7 8 9 10]
    fmt.Println("切片b:",b)  //切片b: [999 888 3 4 5 6 7 8 9 10]
}

  切片的长度和容量

  切片的长度指的是目前切片多大,容量指的是切片总共能存多少

  len:内置函数查看长度

  cap:内置函数查看容量,只针对于切片类型

  数组类型a

1
2
3
4
5
6
7
import "fmt"
 
func main() {
    var a [10]int=[10]int{1,2,3,4,5,6,7,8,9,10}
    fmt.Println(len(a))  //10 数组只有个长度
    fmt.Println(cap(a))  //10 数组没有容量这一说,但是用的时候不报错(没有人这么用)
}

  切片类型b

1
2
3
4
5
6
7
8
import "fmt"
 
func main() {
    var a [10]int=[10]int{1,2,3,4,5,6,7,8,9,10}
    var b []int=a[:]
    fmt.Println(len(b))  //10 b切片的长度是10
    fmt.Println(cap(b))  //10 b切片的容量是:10
}
1
2
3
4
5
6
7
8
9
10
11
12
import "fmt"
 
func main() {
    var a [10]int=[10]int{1,2,3,4,5,6,7,8,9,10}
    var b []int=a[2:4]
    a[0]=999
    b[0]=999
    fmt.Println(a)  //[999 2 999 4 5 6 7 8 9 10]
    fmt.Println(b)  //[999 4]
    fmt.Println(len(b))  //b切片的长度是2
    fmt.Println(cap(b))  //b切片的容量是:8   指向起始位置开始到末尾
}
1
2
3
4
5
6
7
8
import "fmt"
 
func main() {
    var a [10]int=[10]int{1,2,3,4,5,6,7,8,9,10}
    var b []int=a[7:8]   // 第一个数组和最后一个数字都可以不写
    fmt.Println(len(b))  //b切片的长度是1
    fmt.Println(cap(b))  // b切片的容量是:3   指向起始位置开始到末尾
}

  切片底层基于数组,指向数组的某个位置

  切片的容量是从指向位置开始到数组结尾的个数

  

posted @   那就凑个整吧  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示