Golang笔记--切片(slice)的使用

切片是一个引用类型,内部结构包括地址、长度、和容量,实际上切片是数组的一个引用,声明切片可以有几种方式

直接声明,该声明方式,切片的内容是一个nil,长度和容量都是0。

var slice []int
fmt.Printf("sliceMake长度%v,容量%v,初始值%v\n", len(slice), cap(slice), slice)
if slice == nil {
	fmt.Println("slice is nil")
}

make关键字声明,该声明方式,切片的内容不是一个nil,长度和容量都是0。

//make声明和创建
sliceMake := make([]int, 0)
if sliceMake == nil {
	fmt.Println("sliceMake is nil")
}
fmt.Printf("sliceMake长度%v,容量%v,初始值%v\n", len(sliceMake), cap(sliceMake), sliceMake)

sliceMake1 := make([]int, 5, 10)
fmt.Printf("sliceMake1长度%v,容量%v,初始值%v\n", len(sliceMake1), cap(sliceMake1), sliceMake1)

直接声明和初始化,该方式的过程是先创建了一个数组,然后在创建切片指向该数组

//直接声明和初始化
var areaSlice = []string{"广州", "北京", "上海", "深圳", "武汉", "重庆", "成都", "洛阳"}
fmt.Printf("areaSlice长度%v,容量%v,初始值%v\n", len(areaSlice), cap(areaSlice), areaSlice)

根据数组切分初始化切片,该方式有个特别注意的地方,就是切片的容量怎么定义,按该方式去初始化,出来切片的容量是从他第一个元素开始数,到其底层元素数组元素末尾的个数,拿下面这个areaArr[:3]来说,该切片的长度是从底层数组第0个元素开始计算,直到第3个元素切割(不包括3),所以他的长度是3,而容量则是是从底层数组第0个元素开始计算,直到areaArr数组的最后一个元素,也就是areaSlice的容量其实是8,

//数组切分创建和初始化切片
var areaArr = [...]string{"广州", "北京", "上海", "深圳", "武汉", "重庆", "成都", "洛阳"}
//忽略掉slice的起始索引,表示从数组的起始位置进行切分
areaSlice1 := areaArr[:3]
fmt.Printf("areaSlice1长度%v,容量%v,初始值%v\n", len(areaSlice1), cap(areaSlice1), areaSlice1)

//忽略掉slice的结束索引,表示从使用数组的长度作为结束索引
areaSlice2 := areaArr[4:]
fmt.Printf("areaSlice2长度%v,容量%v,初始值%v\n", len(areaSlice2), cap(areaSlice2), areaSlice2)
//同时忽略开始和结束索引,就是包含数组所有元素的一个slice
areaSlice3 := areaArr[:]
fmt.Printf("areaSlice3长度%v,容量%v,初始值%v\n", len(areaSlice3), cap(areaSlice3), areaSlice3)

切片的遍历

//range方式
var areaSlice = []string{"广州", "北京", "上海", "深圳", "武汉", "重庆", "成都", "洛阳"}
for index, item := range areaSlice {
	fmt.Printf("areaSlice遍历第%v个元素的值为%v\n", index, item)
}
//for方式
for i := 0; i < len(areaSlice); i++ {
	fmt.Printf("areaSlice遍历第%v个元素的值为%v\n", i, areaSlice[i])
}

追加切片元素(append)

sliceMake := make([]int, 1)
//追加多个元素
sliceMakeAppend := append(sliceMake, 1, 2)
//追加一个元素
sliceMakeAppend1 := append(sliceMakeAppend, 1)

slice1 := []string{"广州", "北京"}
slice2 := []string{"广州", "北京"}
//追加切片
sliceMerge := append(slice1, slice2...)

实际上,append可以在切片声明之后直接追加,而不需要make,因为append底层实现有make方法,在不符合长度的时候,会初始化该切片。

var slice []int
if slice == nil {
	fmt.Printf("slice is nil\n")
}
slice = append(slice, 11)
if slice != nil {
	fmt.Printf("slice is not nil\n")
}
fmt.Printf("slice长度%v,容量%v,初始值%v\n", len(slice), cap(slice), slice)

//输出
slice is nil
slice is not nil
slice长度1,容量2,初始值[11]

复制一个切片(copy)

//切片复制
sliceCopy := []string{"广州", "北京"}
sliceNew := make([]string, 2)
copy(sliceNew, sliceCopy)


切片操作字符串,利用切片可以切割字符串,但是要注意的是,切片切割字符串,索引是按照字节数来计算的,如果碰到有中文或者特殊字符的,切割出来并不是我们预想的结果。

var strByte = "this is test"
testSlice := strByte[:4]
fmt.Printf("testSlice长度%v,初始值%v,首个元素的内存地址%p\n", len(testSlice), testSlice)

//切片字符串,索引代表的是字节数而非rune的数,例如下面的"go语言,"长度为9个字节,一个汉字占用3个字节
var strRune = "go语言,Hello!"
testSlice1 := strRune[:7]
fmt.Printf("testSlice1长度%v,初始值%v,首个元素的内存地址%p\n", len(testSlice1), testSlice1)

碰到字符串是中文或者特殊字符的,可以考虑转为rune类型的切片,再去提取对应的字符串。

var strByte = "this is test"
var strRune = "go语言,Hello!"
var tempByte = []byte(strByte)
fmt.Printf("tempByte长度%v,容量%v,初始值%v,首个元素的内存地址%p\n", len(tempByte), cap(tempByte), tempByte, &tempByte[0])
var newByteSlice = make([]byte, 0)
for i := 0; i < 4; i++ {
	newByteSlice = append(newByteSlice, tempByte[i])
}
newStr := string(newByteSlice)
fmt.Printf("newStr值%v,类型%T\n", newStr, newStr)

var tempRune = []rune(strRune)
fmt.Printf("tempRune长度%v,容量%v,初始值%v,首个元素的内存地址%p\n", len(tempRune), cap(tempRune), tempRune, &tempRune[0])
var newRuneSlice = make([]rune, 0)
for i := 0; i < 7; i++ {
	newRuneSlice = append(newRuneSlice, tempRune[i])
}
newRuneStr := string(newRuneSlice)
fmt.Printf("newStr值%v,类型%T\n", newRuneStr, newRuneStr)

上一篇:记录golang常用库-json处理

下一篇:linux环境PostgreSQL安装

关注公众号

发表评论