golang 切片
slice
切片的底层类似一个struct
struct{
ptr *[]byte//指针
len int//长度
cap int//容量(扩容原理)
}
slice知识点
package main
import (
"fmt"
)
func test(slice []int) {
slice[0] = 100
//会改变切片的值,因为传进来的切片是指针,属于实参传递了
//这里有可能会造成内存泄露
//重点!!!,这里跟c++的vector区别
}
func main() {
var intArr [5]int = [...]int{1, 22, 33, 66, 99}
slice := intArr[1:3] //等效于 [1.3)
fmt.Println(slice)
fmt.Println(&intArr[1])
fmt.Println(&slice[0])
//cap类似c++vector扩容原理
//相当于切片和数组共用一个内存,但切片三个部分组成
//指向的引用(数组的地址) 长度(len) 大小(cap)
//类似struct的结构
//struct{
// ptr *[2]int
// len int
// cap int
//}
//切片的第一种用法
var strslice []string = []string{"tom", "ammy", "bob"}
fmt.Println(strslice)
fmt.Println(len(strslice))
fmt.Println(cap(strslice))
//切片的第二种用法 类似make 但cap跟len一样
var doubleslice []float64 = make([]float64, 5, 10)
doubleslice[1] = 1.0
doubleslice[3] = 12.2
fmt.Println(&doubleslice[0])
fmt.Println(doubleslice)
fmt.Println(len(doubleslice))
fmt.Println(cap(doubleslice))
//切片的第三种用法var name []type = make([]type,len,cap)
//对于第一种,结构是一样的,但对外是不显示[]float64这个数组,只能靠doubleslice去访问
//类似struct的结构
//struct{
// ptr *[5]float64
// len int
// cap int
//}
//切片循环
var intarry [7]int = [...]int{1, 2, 3, 4, 5, 6, 7}
//intslice := intarry[1:4] //[1,4)
//intslice := intarry[:4] //[0,4)
//intslice := intarry[1:len(intarry)] //[1,7]
intslice := intarry[:] //[0,7]
//for基本版
for i := 0; i < len(intslice); i++ {
fmt.Printf("intslie[%v]:%v\n", i, intslice[i])
}
//for-range
fmt.Println()
for i, v := range intslice {
fmt.Printf("intslie[%v]:%v\n", i, v)
}
strslice = append(strslice, "ammi")
fmt.Println(strslice, len(strslice), cap(strslice)) //cap变为6 扩容
slice = append(slice, 1, 2, 3)
//切片改变,但不改变原本的intArr数组
fmt.Println(slice)
fmt.Println(intArr)
slice = append(slice, slice...) //切片double
// !后者只能是切片,不能是数组 or else
// !后者只能是切片,不能是数组 or else
fmt.Println(slice, len(slice), cap(slice))
//copy 深拷贝
//copy 深拷贝
var slice2 []int = make([]int, 12)
copy(slice2, slice)
fmt.Println(slice2)
test(slice2)
fmt.Println(slice2)
}
string&slice
package main
import (
"fmt"
)
func main() {
//string底层是一个byte数组,因此string也可以切片处理
str := "abcdefg@123"
//使用切片获取到123
slice := str[8:]
fmt.Println(slice)
//str[0]='z'
//直接报错,原因是string是不可变的,不能按照这样改
//修改的话,过程:string->[]byte/或者[]rune->修改重写转成string
arr1 := []byte(str)
arr1[0] = 'z'
str = string(arr1)
fmt.Println(str)
//细节 这种只能处理英文和数字,无法处理中文(三个字节)
//细节 这种只能处理英文和数字,无法处理中文(三个字节)
//要修改中文 使用[]rune
arr2 := []rune(str)
arr2[0] = '中'
str = string(arr2)
fmt.Println(str)
}
slice内存泄漏与防止
用新空数组append,用扩容机制防止内存共用问题
(扩容可以让头部指针变化,数据分开,不会导致一个切片被回收导致另外一个(跟前者有同一块底层数组)形成孤儿数据)