08 Golang引用类型

您所在的位置:网站首页 golang中的引用类型包括 08 Golang引用类型

08 Golang引用类型

2024-02-19 03:01| 来源: 网络整理| 查看: 265

08 Golang引用类型——切片 learninginto · · 873 次点击 · · 开始浏览     这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。 第一次,站长亲自招 Gopher 了>>> 切片

切片(slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。

切片是一个引用类型,它的内部结构包括地址、长度和容量。

声明切片类型的基本语法如下:

var name []T

其中name表示变量名,T表示切片中的元素类型

var arr1 []int fmt.Printf("%v-%T-长度:%v", arr1, arr1, len(arr1))//[]-[]int-长度:4

方式二:定义时初始化

var arr1 = []int{1, 3, 5, 7} fmt.Printf("%v-%T-长度:%v", arr1, arr1, len(arr1))//[]-[]int-长度:4

方式三:赋值时带下标

var arr1 = []int{1:2, 2:4, 5:6} fmt.Printf("%v-%T-长度:%v", arr1, arr1, len(arr1)) //[0 2 4 0 0 6]-[]int-长度:6 nil

golang中,当声明了一个变量,却还并没有赋值值,golang中会自动赋值一个默认值。

类型 默认值 bool false numbers 0 string "" pointers nil slices(切片) nil maps/channels/functions nil

golang中声明切片的默认值是nil

var arr1 []int fmt.Println(arr1 === nil) //true 切片的循环遍历 for var strSlice = []string{"php", "java", "nodejs", "golang"} for i := 0; i < len(strSlice); i++{ fmt.Println(strSlice[i]) } for range var strSlice = []string{"php", "java", "nodejs", "golang"} for k, v := range strSlice { fmt.Println(k, v) } } 基于数组定义切片

获取数组中的所有值

a := [5]int{1, 3, 5, 7, 9} b := a[:] fmt.Printf("%v-%T", b, b) //[1 3 5 7]-[]int

截取数组的某一部分[)——左包右不包

a := [5]int{1, 3, 5, 7, 9} b := a[1:4] c := a[3:]//获取第三个下标之后的数据 d := a[:3]//获取第三个下标之前的数据 fmt.Printf("%v-%T\n", b, b)//[3 5 7]-[]int fmt.Printf("%v-%T", c, c)//[5, 7]-[]int fmt.Printf("%v-%T", d, d)//[1 3 5]-[]int 切片再切片

除了基于数组得到切片,还可以通过切片来得到切片

a := []string{"北京","上海","广州","深圳","成都","重庆"} b := a[1:] fmt.Printf("%v-%T\n", b, b)//[上海 广州 深圳 成都 重庆] 切片的长度及容量

切片拥有自己的长度和容量,可以通过内置的len()函数求长度,cap()求容量。

切片的本质就是对底层数组的封装,它包含了三个信息:底层数据的指针、切片的长度(len)和切片的容量(cap)

长度是它所包含的元素个数

容量是从它的第一个元素开始,到其底层数组元素末尾的个数

s := []int{1, 2, 3, 4, 5, 6} fmt.Printf("长度%d 容量%d", len(s), cap(s)) //长度6 容量6 a := s[2:] fmt.Printf("长度%d 容量%d", len(a), cap(a)) //长度4 容量4 b := s[1:3] fmt.Printf("长度%d 容量%d", len(b), cap(b)) //长度2 容量5 c := s[:3] fmt.Printf("长度%d 容量%d", len(c), cap(c)) //长度3 容量6 make()函数来构造切片

make([]T, size, cap)声明一个长度为size,容量为cap的切片

var sliceA = make([]int, 4, 8) fmt.Println(sliceA)//[0 0 0 0] fmt.Printf("%d-%d",len(sliceA), cap(sliceA))//4-8 切片的修改 var sliceA = make([]int, 4, 8) sliceA[0] = 10 sliceA[1] = 12 fmt.Println(sliceA)//[10 12 0 0] sliceB := []string{"js", "java", "go"} sliceB[2] = "node" fmt.Println(sliceB)//[js java node] 切片的扩容append

golang中不能通过下标的方式给切片扩容,需要用到append()方法,类似于js中的concat()

append()后面可以传多个参数

var sliceC []int fmt.Printf("值%v-长度%v-容量%v",sliceC,len(sliceC),cap(sliceC))//值[]-长度0-容量0 sliceC = append(sliceC, 12) fmt.Printf("值%v-长度%v-容量%v",sliceC,len(sliceC),cap(sliceC))//值[12]-长度1-容量1

append合并切片

sliceA := []string{"php","java"} sliceB := []string{"node","go"} sliceA = append(sliceA, sliceB...) fmt.Println(sliceA)//[php java node go] 切片的扩容策略 首先判断,如果新申请容量大于2倍的旧容量,最终容量是新申请的容量 否则判断,如果旧切片的长度小于1024,则最终容量是旧容量的两倍;如果旧切片长度>=1024,则最终容量从旧容量开始循环增加原来的1/4,即(newcap = old.cap, for{newcap += newcap / 4}),直到最终容量大于新申请的容量 如果最终容量计算值溢出,则最终容量就是新申请容量

需要注意的是,切片扩容还会根据切片中元素的类型不同而做不同的处理,比如int和string类型的处理方式就不一样。

var sliceA []int for i := 0; i < 5; i++{ sliceA = append(sliceA, i) fmt.Printf("%v长度%d 容量%d", sliceA, len(sliceA), cap(sliceA)) } //[1]长度1 容量1 //[1 2]长度2 容量2 //[1 2 3]长度3 容量4 //[1 2 3 4]长度4 容量4 //[1 2 3 4 5]长度5 容量8

可以通过查看$GOROOT/src/runtime/slice.go源码,其中扩容相关代码如下:

newcap := old.cap doublecap := newcap + newcap if cap > doublecap { newcap = cap }else { if old.len < 1024{ newcap = doublecap } else { for 0 < newcap && newcap < cap { newcap += newcap / 4 } if newcap


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3