切片 []type,形似C++ vector【Go基础】

切片 []type,形似C++ vector【Go基础】,第1张

文章目录 切片的复制,删除和拼接
切片维护了三个元素:
指向底层数组的指针,切片的元素数量和底层数组的容量。由于有指针的存在,所以切片是引用类型
若多个切片由同一数组而来,则对数组的修改将影响全局

package main

import "fmt"

/*
切片的本质就是一个框,框住了一块连续的内存
属于引用类型,真正的数据保存在底层数组中
*/

func main() {
	//普通slice
	var slice_1 bool = false
	if slice_1 {
		var a []string
		a = append(a, "hello")
		fmt.Println(a, len(a), cap(a))

		var b [][]string = [][]string{
			[]string{"hello"},
			[]string{"world"},
		}
		fmt.Println(b)
	}

	//由数组得到切片
	//切片的长度是元素的个数,切片的容量是底层数组从切片的第一个元素到最后一个元素的数量
	var slice_2 bool = false
	if slice_2 {
		a1 := [...]int64{1, 3, 5, 7}

		a2 := a1[0:3] //基于一个数组进行切割,左闭右开,包左不包右
		fmt.Print("len:", len(a2), " cap:", cap(a2), "\n")
		a3 := a1[1:]
		fmt.Println(a3)
	}

	//从切片再切片时,会将a1构造成数组,
	//切片是引用类型,都指向底层的数组
	var slice_3 bool = false
	if slice_3 {
		a1 := []int{1, 3, 5, 7, 9, 11}
		a2 := a1[0:3]
		fmt.Print("len:", len(a2), " cap:", cap(a2), "\n")
		a1[0] = 9
		fmt.Println("a1[0]:", a1[0], " a2[0]:", a2[0])

		a2[1] = 9
		fmt.Println("a1[1]:", a1[1], " a2[1]:", a2[1])
	}

	//a[low:high]为简单的切片表达式
	//a[low:high:max]为完整的切片表达式,与简单切片表达式a[low:high]想同类型,相同长度和元素的切片。另外,它会将得到的结果切片容量设置为max - low
	//在完整切片表达式中只有第一个索引值low可以省略,省略时默认为0,并且max需要大于hight
	var slice_4 bool = false
	if slice_4 {
		a1 := []int{1, 3, 5, 7, 9, 11}
		a2 := a1[0:4]
		a3 := a1[0:4:5]
		fmt.Printf("a2 t:%v len(t):%v cap(t)%v\n", a2, len(a2), cap(a2)) //len(t):4 cap(t)6
		fmt.Printf("a3 t:%v len(t):%v cap(t)%v\n", a3, len(a3), cap(a3)) //len(t):4 cap(t)5
	}

	/*
		make函数构造切片 make([]Type, len, cap) Type cap省略时,cap==len
		第二个整数参数可以提供给
		指定不同的容量; 它必须不小于长度。 例如,make([]int, 0, 10) 分配一个底层数组
		大小为 10 并返回长度为 0 且容量为 10 的切片,即由这个底层数组支持
	*/
	var slice_5 bool = false
	if slice_5 {
		a1 := make([]int, 5, 10)
		fmt.Printf("a1 t:%v len(t):%v cap(t)%v\n", a1, len(a1), cap(a1))
	}

	/*
		切片不能直接比较,不能使用==判断两个切片是否含有全部相等元素
		唯一合法的 *** 作时和nil比较,一个nil的切片并没有底层数组,即长度和容量0
		但是长度和容量为0的切片不一定是nil
	*/
}


切片的复制,删除和拼接
package main

import "fmt"

/*
切片的本质就是一个框,框住了一块连续的内存
属于引用类型,真正的数据保存在底层数组中
*/

func main() {
	var slice_1 bool = false
	//append追加元素  扩容策略可在 $GOROOT/src/runtime/slice.go
	if slice_1 {
		a1 := make([]string, 0, 10)
		fmt.Println("len:", len(a1), " cap:", cap(a1))
		a1 = append(a1, "hello")
		fmt.Println("len:", len(a1), " cap:", cap(a1))
	}

	var slice_2 bool = false
	//copy 复制切片,避免了浅拷贝
	if slice_2 {
		a1 := make([]int64, 1, 5)
		a2 := a1
		a1[0] = 1
		fmt.Println("len:", len(a1), " cap:", cap(a1), " a1[0]:", a1[0])
		fmt.Println("len:", len(a2), " cap:", cap(a2), " a2[0]:", a2[0])

		a1 = append(a1, a2...)
		fmt.Println("len:", len(a1), " cap:", cap(a1), " ", a1[0], a1[1])
		fmt.Println("len:", len(a2), " cap:", cap(a2), " ", a2[0])

		a3 := []int{1, 3, 5}
		// var a4 []int //此时a4无内存 为nil 无法拷贝,应该使用make
		a4 := make([]int, 2, 5)
		copy(a4, a3)
		fmt.Println(a3, a4) //实际被copy过去的长度为2和3的交集 也就是2
	}

	/*
		没有删除元素的方法, 如果要从切片a中删除下标为index的元素
		 *** 作方法为 a = append(a[:index], a[index + 1:]...)
	*/
	var slice_3 bool = false
	if slice_3 {
		a := []int{1, 3, 5, 7, 9}
		a = append(a[:2], a[3:]...)
		fmt.Println(a)
		fmt.Println(cap(a)) //cap仍然是5

		x1 := [5]int{1, 3, 5, 7, 9}
		a2 := x1[:]
		a2 = append(a2[:2], a2[3:]...)
		fmt.Println("x1:", x1) //[1 5 5 7 9]
		fmt.Println("a2:", a2, " cap(a2):", cap(a2), " len(a2):", len(a2))

		a3 := make([]int, 5, 10)
		for i := 0; i < 10; i++ {
			a3 = append(a3, i)
		}
		fmt.Println("a3:", a3)
	}

	//关于append删除切片中的某个元素
	var slice_4 bool = true
	if slice_4 {
		a1 := [...]int{1, 3, 5, 7, 9, 11, 13, 17}
		s1 := a1[:]
		s1 = append(s1[:1], s1[2:]...)
		fmt.Println(s1)
		fmt.Println(a1)
	}
}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/994651.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存