go語(yǔ)言中切片Slice與數(shù)組Array對(duì)比以及panic:?runtime?error:?index?out?of?range問(wèn)題解決
前言
在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)題的處理辦法就是直接去官方,看源碼??纯吹谝皇仲Y料怎么講!
長(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í)際開發(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開始,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和技巧~
到此這篇關(guān)于go語(yǔ)言中切片Slice與數(shù)組Array對(duì)比以及panic: runtime error: index out of range問(wèn)題解決的文章就介紹到這了,更多相關(guān)go語(yǔ)言切片Slice和數(shù)組Array內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go實(shí)現(xiàn)整合Logrus實(shí)現(xiàn)日志打印
這篇文章主要介紹了Go實(shí)現(xiàn)整合Logrus實(shí)現(xiàn)日志打印,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07
golang獲取變量或?qū)ο箢愋偷膸追N方式總結(jié)
在golang中并沒(méi)有提供內(nèi)置函數(shù)來(lái)獲取變量的類型,但是通過(guò)一定的方式也可以獲取,下面這篇文章主要給大家介紹了關(guān)于golang獲取變量或?qū)ο箢愋偷膸追N方式,需要的朋友可以參考下2022-12-12
golang字符串轉(zhuǎn)64位整數(shù)的示例代碼
這篇文章主要介紹了golang字符串轉(zhuǎn)64位整數(shù),在Go語(yǔ)言中,可以使用strconv包中的ParseInt函數(shù)將字符串轉(zhuǎn)換為64位整數(shù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09
手把手帶你走進(jìn)Go語(yǔ)言之類型轉(zhuǎn)換
每個(gè)函數(shù)都可以強(qiáng)制將一個(gè)表達(dá)式轉(zhuǎn)換成某種特定數(shù)據(jù)類型,本文給大家介紹了在Go語(yǔ)言中類型轉(zhuǎn)換的具體用法,講述的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值2021-09-09
Go語(yǔ)言編譯時(shí)為exe添加圖標(biāo)和屬性信息的方法
在使用Go語(yǔ)言開發(fā)應(yīng)用程序時(shí),有個(gè)非常方便的地方就是編譯得到的可執(zhí)行文件可以不依賴任何動(dòng)態(tài)鏈接庫(kù)、并且不需要任何運(yùn)行環(huán)境即可運(yùn)行,本文給大家介紹Go編譯時(shí)為exe添加圖標(biāo)和屬性信息的方法,需要的朋友可以參考下2023-09-09
golang協(xié)程與線程區(qū)別簡(jiǎn)要介紹
這篇文章主要介紹了golang協(xié)程與線程區(qū)別簡(jiǎn)要介紹,進(jìn)程是操作系統(tǒng)資源分配的基本單位,是程序運(yùn)行的實(shí)例,線程是操作系統(tǒng)調(diào)度到CPU中執(zhí)行的基本單位2022-06-06
golang中struct和interface的基礎(chǔ)使用教程
Go不同于一般的面向?qū)ο笳Z(yǔ)言,需要我們好好的學(xué)習(xí)研究,下面這篇文章主要給大家介紹了關(guān)于golang中struct和interface的基礎(chǔ)使用的相關(guān)資料,需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03

