• Go切片


    1. 切片的创建和使用

    package main
    
    import "fmt"
    
    func main() {
    	/*
    	数组array:
    		存储一组相同数据类型的数据结构。
    			特点:定长
    
    	切片slice:
    		同数组类似,也叫做变长数组或者动态数组。
    			特点:变长
    		是一个引用类型的容器,指向了一个底层数组。
    
    	切片创建:
    		1. var 切片名 [] 数据类型
    
    		2. var 切片名 = [] 数据类型{元素1,元素2。。。}
    
    		3. 切片名 := []数据类型{元素1,元素2。。。}
    
    		4. 切片名 := make([]int, 5 ,10)
    
    		5. 切片名 := make([]int, 5)       
    			第一个参数:类型
    				slice,map,chan
    			第二个参数:长度len
    				实际存储元素的数量
    			第三个参数:容量cap
    				最多能够存储的元素的数量
    
    		6. 切片名 := []数据类型(变量)
    
    	append(),专门用于向切片的尾部追加元素
    		slice = append(slice, elem1, elem2)
    		slice = append(slice, anotherSlice...)
    	 */
    	//1.数组
    	arr := [4]int{1, 2, 3, 4} //定长
    	fmt.Println(arr)          //[1 2 3 4]
    
    	//2.切片
    	var s1 []int
    	fmt.Println(s1) //[]
    
    	s2 := []int{1, 2, 3, 4} //变长
    	s100 := []int(s2)
    	fmt.Println("s100-->", s100)
    	fmt.Printf("%p--%p", s2, s100) //0xc000060160--0xc000060160
    	fmt.Println(s2)                //[1 2 3 4]
    	fmt.Printf("%T,%T
    ", arr, s2) //[4]int,[]int
    
    	//make创建切片
    	s3 := make([]int, 3, 8)
    	fmt.Println(s3)                               //[0 0 0]
    	fmt.Printf("容量:%d,长度:%d
    ", cap(s3), len(s3)) //容量:8,长度:3
    	s3[0] = 1
    	s3[1] = 2
    	s3[2] = 3
    	fmt.Println(s3) //[1 2 3]
    	//fmt.Println(s3[3]) //panic: runtime error: index out of range
    
    	//append()
    	s4 := make([]int, 0, 5)
    	fmt.Println(s4) //[]
    	s4 = append(s4, 1, 2)
    	fmt.Println(s4) //[1 2]
    	//s4指向新的底层数组
    	s4 = append(s4, 3, 4, 5, 6, 7)
    	fmt.Println(s4)        //[1 2 3 4 5 6 7]
    	s4 = append(s4, s3...) //[1 2 3 4 5 6 7 1 2 3]
    	fmt.Println(s4)
    
    	//遍历切片
    	for i := 0; i < len(s4); i++ {
    		fmt.Println(s4[i])
    	}
    
    	for i, v := range s4 {
    		fmt.Printf("%d-->%d
    ", i, v)
    	}
    
    }

    2. 切片是引用了底层数组

    package main
    
    import "fmt"
    
    func main() {
    	/*
    	切片Slice:
    		1.每一个切片引用了一个底层数组
    		2.切片本身不存储任何数据,都是这个底层数组存储,所以修改切片也就是修改这个数组中的数据
    		3.当向切片中添加数据时,如果没有超过容量,直接添加,如果超过容量,自动扩容(成倍增长)
    		4.切片一旦扩容,就是重新指向一个新的底层数组
    	 */
    	s1 := []int{1, 2, 3}
    	fmt.Println(s1)
    	fmt.Printf("len:%d,cap:%d
    ", len(s1), cap(s1)) //len:3,cap:3
    	fmt.Printf("%p
    ", s1)
    
    	s1 = append(s1, 4, 5)
    	fmt.Println(s1)
    	fmt.Printf("len:%d,cap:%d
    ", len(s1), cap(s1)) //len:5,cap:6
    	fmt.Printf("%p
    ", s1)
    
    	s1 = append(s1,6,7,8)
    	fmt.Println(s1)
    	fmt.Printf("len:%d,cap:%d
    ", len(s1), cap(s1)) //len:8,cap:12
    	fmt.Printf("%p
    ", s1)
    
    	s1 = append(s1,9,10)
    	fmt.Println(s1)
    	fmt.Printf("len:%d,cap:%d
    ", len(s1), cap(s1)) //len:10,cap:12
    	fmt.Printf("%p
    ", s1)
    
    	s1 = append(s1,11,12,13,14,15)
    	fmt.Println(s1)
    	fmt.Printf("len:%d,cap:%d
    ", len(s1), cap(s1)) //len:15,cap:24
    	fmt.Printf("%p
    ", s1)
    }
    

    3. slice := arr[start:end]

    package main
    
    import "fmt"
    
    func main() {
    	/*
    	slice := arr[start:end]
    	 	切片中的数据:[start,end)
    	 	arr[:end],从头到end
    	 	arr[start:]从start到末尾
    
    	 从已有的数组上,直接创建切片,该切片的底层数组就是当前的数组。
    	 	长度是从start到end切割的数据量。
    		但是容量从start到数组的末尾。
    	  */
    	a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    	fmt.Println("----------1.已有数组直接创建切片--------------------")
    	s1 := a[:5]  //1-5
    	s2 := a[3:8] //4-8
    	s3 := a[5:]  // 6-10
    	s4 := a[:]   // 1-10 
    	fmt.Println("a:", a) //a: [1 2 3 4 5 6 7 8 9 10]
    	fmt.Println("s1:", s1) //s1: [1 2 3 4 5]
    	fmt.Println("s2:", s2) //s2: [4 5 6 7 8]
    	fmt.Println("s3:", s3) //s3: [6 7 8 9 10]
    	fmt.Println("s4:", s4) //s4: [1 2 3 4 5 6 7 8 9 10]
    
    	fmt.Printf("%p
    ",&a) //0xc0000680a0
    	fmt.Printf("%p
    ",s1) //0xc0000680a0
    
    	fmt.Println("----------2.长度和容量--------------------")
    	fmt.Printf("s1	len:%d,cap:%d
    ",len(s1),cap(s1)) //s1	len:5,cap:10
    	fmt.Printf("s2	len:%d,cap:%d
    ",len(s2),cap(s2)) //s2	len:5,cap:7
    	fmt.Printf("s3	len:%d,cap:%d
    ",len(s3),cap(s3)) //s3	len:5,cap:5
    	fmt.Printf("s4	len:%d,cap:%d
    ",len(s4),cap(s4)) //s4	len:10,cap:10
    
    
    	fmt.Println("----------3.更改数组的内容--------------------")
    	a[4] =100
    	fmt.Println(a) //[1 2 3 4 100 6 7 8 9 10]
    	fmt.Println(s1) //[1 2 3 4 100]
    	fmt.Println(s2) //[4 100 6 7 8]
    	fmt.Println(s3) //[6 7 8 9 10]
    
    	fmt.Println("----------4.更改切片的内容--------------------")
    	s2[2] =200
    	fmt.Println(a)
    	fmt.Println(s1)
    	fmt.Println(s2)
    	fmt.Println(s3)
    
    	fmt.Println("----------4.更改切片的内容--------------------")
    	s1 = append(s1,1,1,1,1)
    	fmt.Println(a) //[1 2 3 4 100 1 1 1 1 10]
    	fmt.Println(s1) //[1 2 3 4 100 1 1 1 1]
    	fmt.Println(s2) //[4 100 1 1 1]
    	fmt.Println(s3) //[1 1 1 1 10]
    	fmt.Println("----------5.添加元素切片扩容--------------------")
    	fmt.Println(len(s1),cap(s1)) //9 10
    
    	s1 = append(s1,2,2,2,2,2)
    	fmt.Println(a) //[1 2 3 4 100 1 1 1 1 10]
    	fmt.Println(s1) //[1 2 3 4 100 1 1 1 1 2 2 2 2 2]
    	fmt.Println(s2) //[4 100 1 1 1]
    	fmt.Println(s3) //[1 1 1 1 10]
    	fmt.Println(len(s1),cap(s1)) //14 20
    	//扩容之后指向了新的底层数组的地址
    	fmt.Printf("%p
    ",s1) //0xc000096000
    	fmt.Printf("%p
    ",&a) //0xc0000680a0
    }
    

    4. 数组是引用类型

    package main
    
    import "fmt"
    
    func main() {
    	/*
    
    	按照类型来分:
    		基本类型:int,float,string,bool
    		复合类型:array,slice,map,struct,pointer,function,chan
    
    	按照特点来分:
    		值类型:int,float,string,bool,array
    			传递的是数据副本
    		引用类型:Slice
    			传递的地址,多个变量指向了同一块内存地址,
    
    
    
    	所以:切片是引用类型的数据,存储了底层数组的引用
    	 */
    
    	//1.数组:值类型
    	a1 := [4]int{1,2,3,4}
    	a2 := a1  //值传递:传递的是数据
    	fmt.Println(a1,a1) //[1 2 3 4] [1 2 3 4]
    	a1[0] =100 
    	fmt.Println(a1,a2) //[100 2 3 4] [1 2 3 4]
    
    	//2.切片:引用类型
    	s1 :=[]int{1,2,3,4}
    	s2 := s1
    	fmt.Println(s1,s2) //[1 2 3 4] [1 2 3 4]
    	s1[0] =100
    	fmt.Println(s1,s2) //[100 2 3 4] [100 2 3 4]
    
    	fmt.Printf("%p
    ",s1) //0xc0000601e0
    	fmt.Printf("%p
    ",s2) //0xc0000601e0
    	fmt.Printf("%p
    ",&s1) //0xc00005a440
    	fmt.Printf("%p
    ",&s2) //0xc00005a460
     
    }
    

    5. 深拷贝和浅拷贝

    package main
    
    import "fmt"
    
    func main() {
    	/*
    	深拷贝:拷贝的是数据本身。
    		值类型的数据,默认都是深拷贝:array,int,float,string,bool,struct
    
    
    	浅拷贝:拷贝的是数据 地址。
    		导致多个变量指向同一块内存
    		引用类型的数据,默认都是浅拷贝:slice,map,
    
    		因为切片是引用类型的数据,直接拷贝的是地址。
    
    	func copy(dst, src []Type) int
    		可以实现切片的拷贝
    
    	 */
    
    	s1 := []int{1,2,3,4}
    	//如果make的时候给了len,那么会出现默认值,比如len=3,就是0 0 0
    	s2 := make([]int,0) //len:0,cap:0
    	for i:=0;i<len(s1);i++{
    		s2 = append(s2,s1[i])
    	}
    	fmt.Println(s1) //[1 2 3 4]
    	fmt.Println(s2) //[1 2 3 4]
    
    	s1[0] = 100
    	fmt.Println(s1) //[100 2 3 4]
    	fmt.Println(s2) //[1 2 3 4]
    
    	//copy()
    	s3 := []int{7,8,9}
    	fmt.Println(s2) //[1 2 3 4]
    	fmt.Println(s3) //[7 8 9]
    
    	//copy(s2,s3) //将s3中的元素,拷贝到s2中
    	//copy(s3,s2) //将s2中的元素,拷贝到s3中
    	copy(s3[1:],s2[2:])
    	fmt.Println(s2) //[1 2 3 4]
    	fmt.Println(s3) //[7 3 4]
    
    }
    

    6. 从切片中删除元素

    package main
    func main() {
    	//从开头位置删除
    	//删除开头的元素可以直接移动数据指针
    	a = []int{1, 2, 3}
    	a = a[1:] // 删除开头1个元素
    	a = a[N:] // 删除开头N个元素
    	//也可以不移动数据指针,但是将后面的数据向开头移动,可以用 append 原地完成(所谓原地完成是指在原有的切片数据对应的内存区间内完成,
    	//不会导致内存空间结构的变化)
    	a = []int{1, 2, 3}
    	a = append(a[:0], a[1:]...) // 删除开头1个元素
    	a = append(a[:0], a[N:]...) // 删除开头N个元素
    	//还可以用 copy() 函数来删除开头的元素:
    	a = []int{1, 2, 3}
    	a = a[:copy(a, a[1:])] // 删除开头1个元素
    	a = a[:copy(a, a[N:])] // 删除开头N个元素
    	//从中间位置删除
    	//对于删除中间的元素,需要对剩余的元素进行一次整体挪动,同样可以用 append 或 copy 原地完成
    	a = []int{1, 2, 3, ...}
    	a = append(a[:i], a[i+1:]...)  // 删除中间1个元素
    	a = append(a[:i], a[i+N:]...)  // 删除中间N个元素
    	a = a[:i+copy(a[i:], a[i+1:])] // 删除中间1个元素
    	a = a[:i+copy(a[i:], a[i+N:])] // 删除中间N个元素
    	//从尾部删除
    	//删除开头的元素和删除尾部的元素都可以认为是删除中间元素操作的特殊情况
    	a = []int{1, 2, 3}
    	a = a[:len(a)-1] // 删除尾部1个元素
    	a = a[:len(a)-N] // 删除尾部N个元素
    }
    

      

  • 相关阅读:
    javascript的字段值,私有变量,静态方法声明
    取得序列中某个点的范围边界
    使用wubi安装ubuntu11.04后无线网卡被禁用无法打开解决办法
    WEB前端性能优化
    jQuery的arrayLike
    在手机上安装BT5系统,没错就是破解无线密码的那个
    PHP在子类方法B调用父类的方法A时,不传参数时仍能得到方法B的名称
    讨厌的文本选区
    PHP遍历解析XML为一个数组
    “软工厂代码生成工具”的学习笔记
  • 原文地址:https://www.cnblogs.com/yzg-14/p/12247478.html
Copyright © 2020-2023  润新知