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,用扩容机制防止内存共用问题

(扩容可以让头部指针变化,数据分开,不会导致一个切片被回收导致另外一个(跟前者有同一块底层数组)形成孤儿数据)

posted @ 2022-04-30 15:47  ouluy  阅读(38)  评论(0编辑  收藏  举报