Golang切片slice

skymyyang · · 675 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

切片slice

  • 其本身并不是数组,它指向底层的数组
package main

import (
    "fmt"
)

func main() {
    var s1 []int //这样的话就完成了slice的声明,如果是数组的话,必须在中括号当中必须有明确的数字或3个点
    fmt.Println(s1)

}
  • 作为变成数组的替代方案,可以关联底层数组的局部或全部
package main

import (
    "fmt"
)

func main() {
    var s1 []int //这样的话就完成了slice的声明,如果是数组的话,必须在中括号当中必须有明确的数字或3个点,这是个空slice
    a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
    fmt.Println(s1)
    fmt.Println(a)
    s2 := a[9]
    s3 := a[5:10] //a[5,6,7,8,9],也可以写成a[5:]
    fmt.Println(s2)
    fmt.Println(s3)

}
  • 它的值为引用类型、
  • 可以直接创建或从底层数组获取生成
  • 使用len()获取元素个数,cap()获取容量
  • 一般情况下使用make创建
package main

import (
    "fmt"
)

func main() {
    s1 := make([]int, 3, 10) //括号中第一个参数是类型,第二个参数是长度,第三个是容量,如果不设置容量,它就会认为默认是你的长度
    fmt.Println(len(s1), cap(s1))

}
  • 如果多个slice指向相同底层数组,其中一个的值改变会影响全部
  • make([]T,len,cap)
  • 其中cap可以省略,则和len的值相同
  • len表示存在的元素个数,cap表示容量

slice与底层数组对应的关系image

package main

import (
    "fmt"
)

func main() {
    a := [...]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"}
    sa := a[2:5]
    fmt.Println(sa)
    sb := a[3:5]
    fmt.Println(sb)

}

Reslice

  • Reslice时索引以被slice的切片为准
  • 索引不可以超过slice的切片的容量cap()值
  • 索引越界不会导致底层数组的重新分配而是引发错误
package main

import (
    "fmt"
)

func main() {
    a := [...]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"}
    sa := a[2:5]
    fmt.Println(sa)
    //这里的sa指向的是一个连续的内存块,所以它的最大容量到这个内存块的底部
    fmt.Println(len(sa), cap(sa))
    sb := sa[1:3]
    fmt.Println(sb)
    fmt.Println(len(sb), cap(sb))

}
//PS结果:
PS G:\mygo\src\mytest> go run .\myfirst.go
[c d e]
3 9
[d e]
2 8

Append

  • 可以在slice尾部追加元素
  • 可以将一个slice追加在另一个slice尾部
  • 如果最终长度未超过追加到slice的容量则返回原始slice
  • 如果超过追加的slice的容量则将重新分配数组并拷贝原始数据
package main

import (
    "fmt"
)

func main() {
    s1 := make([]int, 3, 6)
    fmt.Printf("%v, %p \n", s1, s1)
    s1 = append(s1, 1, 2, 3)
    fmt.Printf("%v, %p \n", s1, s1)
    //可以看到两次打印的内存地址是一样的,因为追加的元素没有超出原slice的容量
}

PS G:\mygo\src\mytest> go run .\myfirst.go
[0 0 0], 0xc04203ff50
[0 0 0 1 2 3], 0xc04203ff50
package main

import (
    "fmt"
)

func main() {
    s1 := make([]int, 3, 6)
    fmt.Printf("%v, %p \n", s1, s1)
    s1 = append(s1, 1, 2, 3)
    fmt.Printf("%v, %p \n", s1, s1)
    //可以看到两次打印的内存地址是一样的,因为追加的元素没有超出原slice的容量
    s1 = append(s1, 4, 5, 6)
    fmt.Printf("%v %p \n", s1, s1)
    //此时可以看出,最后一次的打印会重新分配内存地址

}
PS G:\mygo\src\mytest> go run .\myfirst.go
[0 0 0], 0xc04203ff50
[0 0 0 1 2 3], 0xc04203ff50
[0 0 0 1 2 3 4 5 6] 0xc04203a0c0
package main

import (
    "fmt"
)

func main() {
    a := []int{1, 2, 3, 4, 5}
    s1 := a[2:5]
    s2 := a[1:3]
    fmt.Println(s1, s2)
    s1[0] = 9
    fmt.Println(s1, s2) //slice是指向一个底层的数组,当多个slice指向同一个底层的数组的时候,其中一个发生改变,另外的slice都会发生改变

}
PS G:\mygo\src\mytest> go run .\myfirst.go
[3 4 5] [2 3]
[9 4 5] [2 9]
package main

import (
    "fmt"
)

func main() {
    a := []int{1, 2, 3, 4, 5}
    s1 := a[2:5]
    s2 := a[1:3]
    fmt.Println(s1, s2)
    s2 = append(s2, 3, 4, 5, 6, 7, 8, 9, 10) //当append的容量超过底层数组的长度时,会重新分配内存地址并拷贝原始数据
    s1[0] = 9
    fmt.Println(s1, s2) //slice是指向一个底层的数组,当多个slice指向同一个底层的数组的时候,其中一个发生改变,另外的slice都会发生改变

}
PS G:\mygo\src\mytest> go run .\myfirst.go
[3 4 5] [2 3]
[9 4 5] [2 3 3 4 5 6 7 8 9 10]

Copy

package main

import "fmt"

func main() {
    s1 := []int{1, 2, 3, 4, 5, 6}
    s2 := []int{7, 8, 9}
    copy(s1, s2) //将S2赋值到s1当中
    fmt.Println(s1, s2)
}
PS G:\mygo\src\mytest> go run .\mysecond.go
[7 8 9 4 5 6] [7 8 9]
package main

import "fmt"

func main() {
    s1 := []int{1, 2, 3, 4, 5, 6}
    s2 := []int{7, 8, 9}
    s3 := s1[:] //将s1完整的拷贝给s3
    fmt.Println(s1, s2)
    fmt.Println(s3)
    fmt.Printf("%p---%p \n", s1, s3)
}

PS G:\mygo\src\mytest> go run .\mysecond.go
[1 2 3 4 5 6] [7 8 9]
[1 2 3 4 5 6]
0xc04203ff50---0xc04203ff50

有疑问加站长微信联系(非本文作者)

本文来自:博客园

感谢作者:skymyyang

查看原文:Golang切片slice

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

675 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传