go语言---切片类型

切片 slice

  • 切片是具有可变长度相同类型的元素序列, 数组是不可变的;
  • 切片与数组在声明时的最主要区别就是长度;
    • 切片 var slice []string
    • 数组 var array [5]string
  • 数组是值类型,切片是引用类型
  • 切片声明后默认为nil,没有开辟内存空间,不能直接操作切片,需要先初始化,切片只能和nil判等
package main

import "fmt"

func main() {
	declareSlice()
	makeFunc()
	sliceDel()
}

// 声明切片
func declareSlice() {
	var slice1 = []string {"a", "b", "c", "d"}
	fmt.Println(slice1)  // [a b c d]

	// 操作切片与操作数组类似,都是通过脚标
	fmt.Println(slice1[0])  // a
	fmt.Println(slice1[1])  // b

	// 修改
	slice1[0] = "A"
	fmt.Println(slice1)  // [A b c d]

	// 复制,判断值类型还是引用类型
	slice2 := slice1
	slice2[3] = "D"
	fmt.Println("slice1: ", slice1)  // slice1:  [A b c D]
	fmt.Println("slice2: ", slice2)  // slice2:  [A b c D]
	fmt.Printf("slice1: %p, slice2: %p \n", slice1, slice2)  // slice1: 0xc00001a080, slice2: 0xc00001a080
	// 修改其中一个,另一个也跟着变了,且内存地址相同,说明是引用类型
}

/*
go语言中可以使用make函数创建 slice  map  channel  interface
使用make函数定义无内容,但是不为nil的切片,说明已经申请了内存空间
语法: make(类型, 初始长度[,初始容量])  初始容量可以省略,默认和长度相等;
 */
func makeFunc() {
	// 不指定切片容量
	s := make([] int, 0)
	fmt.Println(s==nil)  // false
	fmt.Printf("%p \n", s)  // 0x5a8d48
	fmt.Printf("切片长度:%d, 切片容量:%d \n", len(s), cap(s))  // 切片长度:0, 切片容量:0

	// 指定容量
	s2 := make([] int, 0, 3)
	fmt.Printf("%p \n", s2)  // 0xc0000103a0
	fmt.Printf("切片长度:%d, 切片容量:%d \n", len(s2), cap(s2))  // 切片长度:0, 切片容量:3

	// append()函数, 内建函数,无需导入
	s3 := append(s2, 4, 3, 1, 5, 2)
	fmt.Println(s3)  // [4 3 1 5 2]
	fmt.Printf("%p \n", s3)  // 0xc00000c420
	fmt.Printf("切片长度:%d, 切片容量:%d \n", len(s3), cap(s3))  // 切片长度:5, 切片容量:6

	//append()一次性添加一个切片, 注意切片后要加3个点,可以理解为将切片拆分成一个个元素
	s4 := make([]int, 0)
	s5 := []int{1, 2, 3, 4, 5}
	s4 = append(s4, s5...)
	fmt.Println(s4)
	fmt.Printf("切片长度:%d, 切片容量:%d \n", len(s4), cap(s4))  // 切片长度:5, 切片容量:6

	// 长度与容量变化的联系
	s6 := make([]int,0)
	fmt.Println(s6)
	fmt.Println(len(s6), cap(s6))

	s6 = append(s6,1, 2)
	fmt.Println(s6)
	fmt.Println(len(s6), cap(s6))

	s6 = append(s6,  3, 4)
	fmt.Println(s6)
	fmt.Println(len(s6), cap(s6))

	s6 = append(s6, 5, 6, 7, 8, 9)
	fmt.Println(s6)
	fmt.Println(len(s6), cap(s6))

	s6 = append(s6, 10)
	fmt.Println(s6)
	fmt.Println(len(s6), cap(s6))

	s6 = append(s6, 11)
	fmt.Println(s6)
	fmt.Println(len(s6), cap(s6))

	/*
	[]
	0 0
	[1 2]
	2 2
	[1 2 3 4]
	4 4
	[1 2 3 4 5 6 7 8 9]
	9 10
	[1 2 3 4 5 6 7 8 9 10]
	10 10
	[1 2 3 4 5 6 7 8 9 10 11]
	11 20

	一次性添加多个值时,长度与容量的变化关系:
	如果一次性添加多个值,且添加后的长度大于扩容一次(翻倍后)的大小,容量和长度相等;(比如从2变到4,但是一次添加到5个,就直接为5而非4)
	等到下次添加内容时如果不超出容量大小,在现有的基础上进行翻倍;
	 */
}

func sliceDel() {
	/* go语言标准库中没有提供删除的函数
	利用切片可以取其中一段形成子切片的特性,实现删除元素的效果,
	说白了就是将源切片从要删除的元素那里分成两截,取前后两段拼接,目标位置丢弃;
	 */

	s7 := []int {1, 2, 3, 4, 5, 6, 7}
	fmt.Println("s7: ", s7)  // [1 2 3 4 5 6 7]
	// 删除 脚标为n的元素
	n := 2
	s8 := s7[0:n]
	fmt.Println("s8: ", s8)  // [1 2]
	s8 = append(s8, s7[n+1:]...)  // s7[n+1:] 表示的是从n+1到结尾,即略过了n.
	fmt.Println("s7: ", s7)  // [1 2 4 5 6 7 7]  指针类型,会修改源数据,所以要使用新的
	fmt.Println("s8: ", s8)  // [1 2 4 5 6 7]
}
发布了22 篇原创文章 · 获赞 1 · 访问量 1855

猜你喜欢

转载自blog.csdn.net/weixin_42677653/article/details/105130831