網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
go語(yǔ)言中切片Slice與數(shù)組Array對(duì)比以及panic:?runtime?error:?index?out?of?range問(wèn)題解決_Golang
作者:大錘愛(ài)編程 ? 更新時(shí)間: 2022-09-13 編程語(yǔ)言前言
在go語(yǔ)言的學(xué)習(xí)歷程當(dāng)中,slice數(shù)據(jù)類型引起了我的好奇心。為啥不直接使用Slice,是人性的扭曲還是道德的淪喪~,下面讓我們一探究竟~~
一、go slice是什么
go語(yǔ)言中的slice是一個(gè)基于Array封裝的數(shù)據(jù)結(jié)構(gòu),go語(yǔ)言中slice的使用頻率遠(yuǎn)高于array,其身影頻頻出現(xiàn)在源碼實(shí)現(xiàn)當(dāng)中。slice相對(duì)于Array的優(yōu)點(diǎn)就是其可以動(dòng)態(tài)調(diào)整自己的size,不像Array的Size是固定的。
二、go slice實(shí)戰(zhàn)案例
1.slice創(chuàng)建、使用
slice的創(chuàng)建有兩個(gè)方法分別是使用字面量定義和使用make函數(shù)。除過(guò)slice創(chuàng)建,其他slice的生成辦法均是從現(xiàn)有slice分片或者array上做slice分片操作。
slice創(chuàng)建代碼:
package main import ( "fmt" "reflect" ) func main() { //字面創(chuàng)造Slice sliceOne := []string{"a", "b"} //使用make函數(shù)創(chuàng)造slice sliceTwo := make([]string, 10) sliceThree := make([]int, 10) fmt.Printf("使用字面量創(chuàng)建的slice%s\n",reflect.ValueOf(sliceOne).String()) fmt.Printf("使用make函數(shù)創(chuàng)建的slice:%s\n",reflect.ValueOf(sliceTwo).String()) fmt.Printf("使用make函數(shù)創(chuàng)建的slice:%s\n",reflect.ValueOf(sliceThree).String()) }
程序輸出:
使用字面量創(chuàng)建的slice<[]string Value>
使用make函數(shù)創(chuàng)建的slice:<[]string Value>
使用make函數(shù)創(chuàng)建的slice:<[]int Value>
?
Process finished with the exit code 0
2、slice的長(zhǎng)度和容量概念理解
學(xué)習(xí)過(guò)程中,很多小伙伴會(huì)對(duì)slice的長(zhǎng)度和容量問(wèn)題有著很多混淆。
這個(gè)地方可以把切片比喻成一個(gè)可以裝10個(gè)蘋果的袋子,現(xiàn)在的袋子里面有三顆蘋果。切片的長(zhǎng)度就是袋子已經(jīng)裝的果子的個(gè)數(shù),目前是3個(gè)。切片的容量就是這個(gè)袋子一共能裝多少個(gè)果子,對(duì)于這個(gè)袋子來(lái)說(shuō)就是10。那么把代碼替換成切片,把蘋果替換成元素,是不是就懂了撒~
下面就是該問(wèn)題的處理辦法就是直接去官方,看源碼。看看第一手資料怎么講!
長(zhǎng)度:slice中擁有的元素個(gè)數(shù),如果slice是nil的話,則元素個(gè)數(shù)長(zhǎng)度是0
英文:the number of elements in v; if v is nil, len(v) is zero
容量:slice切片的長(zhǎng)度能夠到達(dá)的最大值
英文:Slice: the maximum length the slice can reach when resliced;
代碼驗(yàn)證環(huán)節(jié):
package main import ( "fmt" ) func main() { sliceOne := []string{"a", "b"} strings := sliceOne[0:1] fmt.Printf("切片的長(zhǎng)度:%d\n",len(strings)) fmt.Printf("切片的容量:%d\n",cap(strings)) }
代碼結(jié)果輸出:
切片的長(zhǎng)度:1
切片的容量:2
代碼原理解析:
strings由sliceOne切片而來(lái),切出來(lái)的片上數(shù)據(jù)有的是0到1,有一個(gè)元素,故其對(duì)應(yīng)的長(zhǎng)度是1。
因?yàn)榍衅且粋€(gè)引用類型,只在原始切片上切出了0到1的位置,剩余的空位還有1,故其容量等于長(zhǎng)度加剩余元素位置數(shù)。
3. 切片擴(kuò)容及slice panic: runtime error: index out of range
slice越界代碼實(shí)例如下:
sliceOne := []string{"a", "b"} //使用make函數(shù)創(chuàng)造slice s := sliceOne[2] fmt.Printf(s)
使用sliceOne[2]語(yǔ)句時(shí),數(shù)組越界報(bào)錯(cuò)。
實(shí)際開(kāi)發(fā)過(guò)程中,總會(huì)有slice容量不夠用的時(shí)候,該怎么擴(kuò)容,如何保證安全擴(kuò)容?
go語(yǔ)言官方提供的擴(kuò)容辦法就是創(chuàng)建一個(gè)新的更大的分片,將老分片的數(shù)據(jù)內(nèi)容遷移到新的切片當(dāng)中。
代碼展示:
package main import ( "fmt" ) func main() { sliceOne := []string{"a", "b"} fmt.Printf("切片擴(kuò)容前") fmt.Printf("切片的長(zhǎng)度:%d\n",len(sliceOne)) fmt.Printf("切片的容量:%d\n",cap(sliceOne)) t := make([]string, len(sliceOne), (cap(sliceOne))*2) copy(t, sliceOne) sliceOne = t fmt.Printf("切片擴(kuò)容后") fmt.Printf("切片的長(zhǎng)度:%d\n",len(sliceOne)) fmt.Printf("切片的容量:%d\n",cap(sliceOne)) }
結(jié)果展示:
切片的長(zhǎng)度:2
切片的容量:2
切片的長(zhǎng)度:2
切片的容量:4
從代碼結(jié)果上看出新切片的長(zhǎng)度是2,容量是4,也再次驗(yàn)證了切片的長(zhǎng)度取決于存放了多少元素,切片的容量取決于已存放的元素?cái)?shù)量加剩余位置數(shù)。
附:go 判斷數(shù)組下標(biāo)是否存在
舉例
現(xiàn)在需要判斷命令行是否傳了參數(shù),即 os.Args[1] 是否存在
如果使用下述的判斷:
func main() { fmt.Println(os.Args[1]) }
會(huì)報(bào)錯(cuò):index out of range
panic: runtime error: index out of range [1] with length 1
?
goroutine 1 [running]:
main.main()
? ? ? ? D:/go_work/test/test4.go:9 +0xbc
exit status 2
現(xiàn)有兩種方式解決:
第一種:
通過(guò)遍歷的方式判斷 key 是否存在
func main() { var result string for k, v := range os.Args { if k == 1 { result = v } } if result != "" { fmt.Printf("os.Args[1] = %s", result) } }
第二種:
由于數(shù)組下標(biāo)從0開(kāi)始,len(arr)-1 為最后一個(gè)元素的下標(biāo),所以判斷所要查詢的 key 是否小于 len(arr) 就可以了
func main() { if len(os.Args)>=2 { fmt.Printf("os.Args[1] = %s", os.Args[1]) } }
總結(jié)
go語(yǔ)言中slice的應(yīng)用和使用相對(duì)來(lái)說(shuō)方便快捷很多,不過(guò)也有一些小小的暗坑等待大家發(fā)現(xiàn)和整理哦~后續(xù)我會(huì)在我的博客中,繼續(xù)發(fā)布有關(guān)于go語(yǔ)言使用的tips和技巧~
原文鏈接:https://blog.csdn.net/alike_u/article/details/125436734
相關(guān)推薦
- 2022-05-19 Python學(xué)習(xí)之異常處理的避坑指南_python
- 2022-08-25 pycharm中keras導(dǎo)入報(bào)錯(cuò)無(wú)法自動(dòng)補(bǔ)全cannot?find?reference分析_pyt
- 2022-04-01 kubeadm報(bào)錯(cuò):The connection to the server localhost:8
- 2022-12-29 Python?Setuptools的?setup.py實(shí)例詳解_python
- 2022-11-25 Python執(zhí)行dos和Linux命令的方法詳解_python
- 2022-07-26 FastDFS-支持雙IP、IPV6
- 2022-09-29 Shell函數(shù)返回值方式_linux shell
- 2022-07-13 Android自定義View實(shí)現(xiàn)簡(jiǎn)易畫板功能_Android
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支