golang笔记7-slice(切片)

什么是切片

        它是基于数组类型做了一层封装,支持自动扩容,拥有相同元素类型的可变长度的序列。

        切片是引用类型,内部结构包含地址、长度和容量,切片一般用于快速的操作一块数据集合。

       

切片的声明

var name []T

name:变量名

T:切片中元素的类型

示例

func main() {
	//切片的定义
	var s1 []int    // 定义一个存放存放int类型元素的切片
	var S2 []string //定义一个string类型的切片

	fmt.Println(s1)
	fmt.Println(S2)

}

切片的操作 

切片的初始化

func main() {
	//切片的定义
	var s1 []int    // 定义一个存放存放int类型元素的切片
	var S2 []string //定义一个string类型的切片

	// 切片的初始化
	fmt.Println(s1 == nil) // true声明切片后如果没有初始化,切片是nil
	s1 = []int{1, 2, 3}
	S2 = []string{"江苏", "北京", "上海"}

	fmt.Println(s1)
	fmt.Println(S2)

}

切片的长度和容量

长度:

        获取切片长度:len()

        切片中元素的个数

容量:

        获取切片容量:cap()

        从切片的第一个元素开始,到底层数组中最后一个元素之间的元素个数

        对于我们直接在代码中初始化的切片,go底层会创建一个数组,然后开始生成切片,直接初始化的切片的长度和容量是相同的。

         切片是引用类型,底层是数组,如过修改指向的数组的值,切片中对应的元素的值也会变化

package main

import "fmt"

func main() {
	var a1 = [...]int{1, 3, 5, 7, 9, 11, 13}
	// 从数组中得到切片
	s1 := a1[0:4] //=> 基于数组切割,左闭右开(左包含右不包含)
	s2 := a1[1:5] //=>
	s3 := a1[:3]  //=> 等同于[0:3]
	s4 := a1[3:]  //=> 等同于[3:len(a1)]
	s5 := a1[:]   //=> 等同于[0:len(a1)]
	//底层数据从切片第一个元素到最后元素的数量是切片的容量
	fmt.Printf("len(s1):%d,cap(s1):%d\n", len(s1), cap(s1)) //len(s1):4,cap(s1):7
	fmt.Printf("len(s2):%d,cap(s2):%d\n", len(s2), cap(s2)) //len(s2):4,cap(s2):6
	fmt.Printf("len(s3):%d,cap(s3):%d\n", len(s3), cap(s3)) //len(s3):3,cap(s3):7
	fmt.Printf("len(s4):%d,cap(s4):%d\n", len(s4), cap(s4)) //len(s4):4,cap(s4):4
	fmt.Printf("len(s5):%d,cap(s5):%d\n", len(s5), cap(s5)) //len(s5):7,cap(s5):7

	s6 := []int{1, 2, 3}
	fmt.Printf("直接初始化切片s6的len(s1):%d,cap(s1):%d\n", len(s6), cap(s6)) //直接初始化切片s6的len(s1):3,cap(s1):3

	fmt.Printf("s1当前值:%d\n", s1) //s1当前值:[1 3 5 7]
	//修改对应数组的值
	a1[2] = 100
	fmt.Printf("修改底层数组的值后,s1值:%d\n", s1) //修改底层数组的值后,s1值:[1 3 100 7]

}

使用make函数创建切片 

        上面的内容是基于数组创建的切片,如果需要动态的创建一个切片,我们需要使用内置的 make() 函数,格式如下:

make([]T size , cap)

T:元素的数据类型

size:切片的长度

cap:切片的容量

func main() {
	// 创建一个长度5,容量10的切片
	s1 := make([]int, 5, 10)
	fmt.Printf("s1=%v,len(s1)=%d,cap(s1)=%d", s1, len(s1), cap(s1)) 
    //s1=[0 0 0 0 0],len(s1)=5,cap(s1)=10
}

切片的比较

        切片是引用类型,不能使用 == 操作符来判断两个切片是否包含全部相等的元素,切片唯一合法的比较是和 nil 比较,一个nil 值的切片是没有初始化的切片,或者说没有引用底层数组,长度和容量都是0,但是我们不能说一个长度和容量是0的切片一定是nil,如果使用make开辟内存空间,设置的长度和容量是0,那这个切片就是nil。

切片的遍历

索引遍历

        

func main() {
	// 创建一个长度5,容量10的切片
	s1 := make([]int, 5, 10)
	s1 = []int{1, 3, 5, 7, 9}
    //切片的下标和数组一样也是从0开始到len-1结束
	for i := 0; i < len(s1); i++ {
		fmt.Println(s1[i])
	}
}

range遍历

func main() {
	// 创建一个长度5,容量10的切片
	s1 := make([]int, 5, 10)
	s1 = []int{1, 3, 5, 7, 9}
	// range 返回第一个参数为下标,第二个参数为切片中的元素
	for i, v := range s1 {
		fmt.Printf("1=%d,v=%d \n", i, v)
	}
}

append 和 copy

append()为切片追加元素

        Go的内置函数 append()可以动态的给切片增加元素,每个切片都会指向一个底层数组,当底层数组不能容纳新增的元素时,切片就会自动按照一定的策略进行扩容,此时切片指向的底层数组就会更换,“扩容”操作往往发生在append()函数调用时

func main() {
	var s1 []int = make([]int, 0)

	for i := 0; i < 5; i++ {
		//使用 append向切片追加元素
		s1 = append(s1, i)
		//打印切片的元素,长度和容量
		fmt.Printf("s1=%v,len(s1)=%d,cap(s1)=%d\n", s1, len(s1), cap(s1))
		/*
			输出: 元素追加成功,长度和容量每次追加都会变大,证明切片的长度是可变的
			s1=[0],len(s1)=1,cap(s1)=1
			s1=[0 1],len(s1)=2,cap(s1)=2
			s1=[0 1 2],len(s1)=3,cap(s1)=4
			s1=[0 1 2 3],len(s1)=4,cap(s1)=4
			s1=[0 1 2 3 4],len(s1)=5,cap(s1)=8

		*/
	}
}

append()一次追加多个元素

func main() {
	var s1 []string = make([]string, 0)
	s1 = append(s1, "北京", "上海", "添加", "重庆")
	fmt.Printf("s1=%v,len(s1)=%d,cap(s1)=%d\n", s1, len(s1), cap(s1))
}

copy 复制切片

        切片是引用类型,直接把一个切片赋值给另外一个切片,修改其中一个切片时,另外一个切片也会跟着变化。

示例:

func main() {
	var s1 []string = make([]string, 0)
	s1 = append(s1, "北京", "上海", "天津", "重庆")
	s2 := s1
	fmt.Printf("s1 = %v\n", s1)
	fmt.Printf("s2 = %v\n", s2)
	//修改s2元素的值,s1也会变化
	s2[2] = "江苏"
	fmt.Printf("s1 = %v\n", s1)
	fmt.Printf("s2 = %v\n", s2)
}

         copy函数可以迅速的讲一个切片的数据复制到另外一个切片空间中,避免直接赋值指向同一块空间的问题。

func main() {
	var s1 []string = make([]string, 0)
	s1 = append(s1, "北京", "上海", "天津", "重庆")
	var s2 = make([]string, len(s1))
	copy(s2, s1)
	fmt.Printf("s2 = %v \n", s2)
	// 修改s2 查看s1会不会变化
	s2[1] = "武汉"
	fmt.Printf("s2 = %v \n", s2)
	fmt.Printf("s1 = %v\n", s1)
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值