Golang切片slice

切片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:mygosrcmytest> 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 
", s1, s1)
	s1 = append(s1, 1, 2, 3)
	fmt.Printf("%v, %p 
", s1, s1)
	//可以看到两次打印的内存地址是一样的,因为追加的元素没有超出原slice的容量
}

PS G:mygosrcmytest> 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 
", s1, s1)
	s1 = append(s1, 1, 2, 3)
	fmt.Printf("%v, %p 
", s1, s1)
	//可以看到两次打印的内存地址是一样的,因为追加的元素没有超出原slice的容量
	s1 = append(s1, 4, 5, 6)
	fmt.Printf("%v %p 
", s1, s1)
	//此时可以看出,最后一次的打印会重新分配内存地址

}
PS G:mygosrcmytest> 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:mygosrcmytest> 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:mygosrcmytest> 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:mygosrcmytest> 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 
", s1, s3)
}

PS G:mygosrcmytest> go run .mysecond.go
[1 2 3 4 5 6] [7 8 9]
[1 2 3 4 5 6]
0xc04203ff50---0xc04203ff50
原文地址:https://www.cnblogs.com/skymyyang/p/7614864.html