go语言 - slice

一、说明:

 

slice 并不是数组或数组指针。它通过内部指针和相关属性引⽤用数组⽚片段,以实现变⻓长⽅方案

 

二、练习:

 

代码如下

package main

import (
	"fmt"
)

/*
	1. slick是引用类型,但自身是结构体,值拷贝专递
	2. 熟性len 表示可用元素数量,读写操作不能超过该限制
	3. 属性cap 表示最大扩张容量,不能超出数组限制
	4. 如果slice == nil,则len、cap 结果都等于0
*/

func main() {

	//创建slice
	data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	//[low : high : max], len = high- low , cap = max - low; tip:创建表达式,使用的是索引
	slice1 := data[1:4:5]
	slice2 := data[:6:8]
	slice3 := data[5:]
	slice4 := data[:3]
	slice5 := data[:]
	fmt.Printf("slice1 的len 为:%d, cap 为:%d, value为:%v \n", len(slice1), cap(slice1), slice1)
	fmt.Printf("slice1 的len 为:%d, cap 为:%d, value为:%v \n", len(slice2), cap(slice2), slice2)
	fmt.Printf("slice1 的len 为:%d, cap 为:%d, value为:%v \n", len(slice3), cap(slice3), slice3)
	fmt.Printf("slice1 的len 为:%d, cap 为:%d, value为:%v \n", len(slice4), cap(slice4), slice4)
	fmt.Printf("slice1 的len 为:%d, cap 为:%d, value为:%v \n", len(slice5), cap(slice5), slice5)

	//读写操作,实际目标是底层数组,需注意索引号的差别
	s := data[2:4]
	s[0] += 100
	s[1] += 200
	fmt.Println(s)
	fmt.Println(data)

	//直接创建slice,自动分配底层数组; 不需要先创建数组, 然后截取一段为slice
	s1 := []int{1, 3, 5, 7, 9}
	fmt.Printf("s1 的len 为:%d, cap 为:%d, value为:%v \n", len(s1), cap(s1), s1)

	//make 创建, 使用基础类型的默认值
	s2 := make([]int, 6, 8)
	fmt.Printf("s2 的len 为:%d, cap 为:%d, value为:%v \n", len(s2), cap(s2), s2)

	s3 := make([]int, 6) //沈略cap, 相当于 cap = len
	fmt.Printf("s2 的len 为:%d, cap 为:%d, value为:%v \n", len(s3), cap(s3), s3)

	//使用make 动态创建slice, 避免了数组必须用常量做长度的麻烦,还可以用指针直接访问底层数组元素
	p := &s1[2]
	*p += 10000
	fmt.Printf("通过指针访问数组底层元素后,s1 的len 为:%d, cap 为:%d, value为:%v \n\n\n", len(s1), cap(s1), s1)

	//[][]T
	twoDimensionSlice()

	//修改
	modify()

	//fmt.Println("\nReslice Demo: ")
	// resliceDemo()

	fmt.Println("\nAppend Demo: ")
	appendDemo()

	fmt.Println("\nAppend Demo2: ")
	appendDemo2()

	fmt.Println("\nCopy Demo: ")
	copyDemo()
}

// [][]T, 是指元素类型为[]T
func twoDimensionSlice() {
	data := [][]int{
		[]int{1, 2, 3},
		[]int{10, 20, 30},
		[]int{100, 200, 300},
	}

	for i, s := range data {
		fmt.Printf("index: %d, slice%d's value: %v \n", i, i, s)
	}
}

//
func modify() {
	data := [5]struct {
		v int
	}{}
	s := data[:]
	data[1].v = 10
	s[2].v = 20

	fmt.Println(data)

	fmt.Printf("%p, %p \n", &data, &data[0])
}

//reslice,指基于已有的slice 创建新的slice对象,以便再cap 允许范围内调整属性
func resliceDemo() {
	s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	s1 := s[2:5]    //[2, 3, 4]
	s2 := s1[2:6:7] //[4,5,6,7]
	s3 := s2[3:6]   //error
	fmt.Println("\nresliceDemo: ")
	fmt.Printf("s1 的len 为:%d, cap 为:%d, value为:%v \n", len(s1), cap(s1), s1)
	fmt.Printf("s2 的len 为:%d, cap 为:%d, value为:%v \n", len(s2), cap(s2), s2)
	fmt.Printf("s3 的len 为:%d, cap 为:%d, value为:%v \n", len(s3), cap(s3), s3)
}

//append 向slice 尾部添加元素,返回新的slice 对象
func appendDemo() {
	s := make([]int, 0, 5)
	fmt.Printf("%p \n", &s)

	s2 := append(s, 1)
	fmt.Printf("s2 的value 为:%v, s2的地址为: %p \n", s2, &s2)

	s2 = append(s2, 11)
	fmt.Printf("s2 的value 为:%v, s2的地址为: %p \n", s2, &s2)

	fmt.Printf("s的value 为:%v, s2的value 为: %v \n", s, s2)
}

func appendDemo2() {
	data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	sliceOne := data[1:]
	fmt.Printf("sliceOne' value is : %v \n", sliceOne)

	sliceOne = append(sliceOne, 10)
	fmt.Printf("sliceOne' value is : %v, sliceOne' cap is %d \n", sliceOne, cap(sliceOne))

	sliceTwo := append(sliceOne, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
	fmt.Printf("sliceTwo' value is : %v, sliceTwo' cap is %d \n", sliceTwo, cap(sliceTwo))

	fmt.Printf("data' value is %v, data's pointer is %p, data's cap is %d \n", data, &data, cap(data))
}

/*
	函数 copy 在两个 slice 间复制数据,复制⻓长度以 len ⼩小的为准。两个 slice 可指向同一底层数组,允许元素区间重叠
*/
func copyDemo() {
	data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

	s := data[8:]
	s1 := data[:5]

	fmt.Printf("s 的value 为:%v, s的地址为: %p \n", s, &s)
	fmt.Printf("s1 的value 为:%v, s1的地址为: %p \n", s1, &s1)

	//后面的slice 覆盖前面的slice 中对应下标的元素
	copy(s1, s)
	fmt.Println(s1)
	fmt.Println(s)
	fmt.Println(data)
}

 

你可能感兴趣的:(golang)