go語言怎么定義切片 go切片操作

go語言數組,切片和字典的區別和聯系

、數組 

網站建設哪家好,找創新互聯建站!專注于網頁設計、網站建設、微信開發、成都小程序開發、集團企業網站建設等服務項目。為回饋新老客戶創新互聯還提供了洞頭免費建站歡迎大家使用!

與其他大多數語言類似,Go語言的數組也是一個元素類型相同的定長的序列。

(1)數組的創建。

數組有3種創建方式:[length]Type 、[N]Type{value1, value2, ... , valueN}、[...]Type{value1, value2, ... , valueN} 如下:

復制代碼代碼如下:

func test5() {

var iarray1 [5]int32

var iarray2 [5]int32 = [5]int32{1, 2, 3, 4, 5}

iarray3 := [5]int32{1, 2, 3, 4, 5}

iarray4 := [5]int32{6, 7, 8, 9, 10}

iarray5 := [...]int32{11, 12, 13, 14, 15}

iarray6 := [4][4]int32{{1}, {1, 2}, {1, 2, 3}}

fmt.Println(iarray1)

fmt.Println(iarray2)

fmt.Println(iarray3)

fmt.Println(iarray4)

fmt.Println(iarray5)

fmt.Println(iarray6)

}

結果:

[0 0 0 0 0]

[1 2 3 4 5]

[1 2 3 4 5]

[6 7 8 9 10]

[11 12 13 14 15]

[[1 0 0 0] [1 2 0 0] [1 2 3 0] [0 0 0 0]]

我們看數組 iarray1,只聲明,并未賦值,Go語言幫我們自動賦值為0。再看 iarray2 和 iarray3 ,我們可以看到,Go語言的聲明,可以表明類型,也可以不表明類型,var iarray3 = [5]int32{1, 2, 3, 4, 5} 也是完全沒問題的。

(2)數組的容量和長度是一樣的。cap() 函數和 len() 函數均輸出數組的容量(即長度)。如:

復制代碼代碼如下:

func test6() {

iarray4 := [5]int32{6, 7, 8, 9, 10}

fmt.Println(len(iarray4))

fmt.Println(cap(iarray4))

}

輸出都是5。

(3)使用:

復制代碼代碼如下:

func test7() {

iarray7 := [5]string{"aaa", `bb`, "可以啦", "叫我說什么好", "()"}

fmt.Println(iarray7)

for i := range iarray7 {

fmt.Println(iarray7[i])

}

}

二、切片

Go語言中,切片是長度可變、容量固定的相同的元素序列。Go語言的切片本質是一個數組。容量固定是因為數組的長度是固定的,切片的容量即隱藏數組的長度。長度可變指的是在數組長度的范圍內可變。

(1)切片的創建。

切片的創建有4種方式:

1)make ( []Type ,length, capacity )

2) make ( []Type, length)

3) []Type{}

4) []Type{value1 , value2 , ... , valueN }

從3)、4)可見,創建切片跟創建數組唯一的區別在于 Type 前的“ [] ”中是否有數字,為空,則代表切片,否則則代表數組。因為切片是長度可變的。如下是創建切片的示例:

復制代碼代碼如下:

func test8() {

slice1 := make([]int32, 5, 8)

slice2 := make([]int32, 9)

slice3 := []int32{}

slice4 := []int32{1, 2, 3, 4, 5}

fmt.Println(slice1)

fmt.Println(slice2)

fmt.Println(slice3)

fmt.Println(slice4)

}

輸出為:

[0 0 0 0 0]

[0 0 0 0 0 0 0 0 0]

[]

[1 2 3 4 5]

如上,創造了4個切片,3個空切片,一個有值的切片。

(2)切片與隱藏數組:

一個切片是一個隱藏數組的引用,并且對于該切片的切片也引用同一個數組。如下示例,創建了一個切片slice0,并根據這個切片創建了2個切片 slice1 和 slice2:

復制代碼代碼如下:

func test9() {

slice0 := []string{"a", "b", "c", "d", "e"}

slice1 := slice0[2 : len(slice0)-1]

slice2 := slice0[:3]

fmt.Println(slice0, slice1, slice2)

slice2[2] = "8"

fmt.Println(slice0, slice1, slice2)

}

輸出為:

[a b c d e] [c d] [a b c]

[a b 8 d e] [8 d] [a b 8]

可見,切片slice0 、 slice1 和 slice2是同一個底層數組的引用,所以slice2改變了,其他兩個都會變。

(3)遍歷、修改切片:

復制代碼代碼如下:

func test10() {

slice0 := []string{"a", "b", "c", "d", "e"}

fmt.Println("\n~~~~~~元素遍歷~~~~~~")

for _, ele := range slice0 {

fmt.Print(ele, " ")

ele = "7"

}

fmt.Println("\n~~~~~~索引遍歷~~~~~~")

for index := range slice0 {

fmt.Print(slice0[index], " ")

}

fmt.Println("\n~~~~~~元素索引共同使用~~~~~~")

for index, ele := range slice0 {

fmt.Print(ele, slice0[index], " ")

}

fmt.Println("\n~~~~~~修改~~~~~~")

for index := range slice0 {

slice0[index] = "9"

}

fmt.Println(slice0)

}

如上,前三種循環使用了不同的for range循環,當for后面,range前面有2個元素時,第一個元素代表索引,第二個元素代表元素值,使用 “_” 則表示忽略,因為go語言中,未使用的值會導致編譯錯誤。

只有一個元素時,該元素代表索引。

只有用索引才能修改元素。如在第一個遍歷中,賦值ele為7,結果沒有作用。因為在元素遍歷中,ele是值傳遞,ele是該切片元素的副本,修改它不會影響原本值,而在第四個遍歷——索引遍歷中,修改的是該切片元素引用的值,所以可以修改。

結果為:

~~~~~~元素遍歷~~~~~~

a b c d e

~~~~~~索引遍歷~~~~~~

a b c d e

~~~~~~元素索引共同使用~~~~~~

aa bb cc dd ee

~~~~~~修改~~~~~~

[9 9 9 9 9]

(4)、追加、復制切片:

復制代碼代碼如下:

func test11() {

slice := []int32{}

fmt.Printf("slice的長度為:%d,slice為:%v\n", len(slice), slice)

slice = append(slice, 12, 11, 10, 9)

fmt.Printf("追加后,slice的長度為:%d,slice為:%v\n", len(slice), slice)

slicecp := make([]int32, (len(slice)))

fmt.Printf("slicecp的長度為:%d,slicecp為:%v\n", len(slicecp), slicecp)

copy(slicecp, slice)

fmt.Printf("復制賦值后,slicecp的長度為:%d,slicecp為:%v\n", len(slicecp), slicecp)

}

追加、復制切片,用的是內置函數append和copy,copy函數返回的是最后所復制的元素的數量。

(5)、內置函數append

內置函數append可以向一個切片后追加一個或多個同類型的其他值。如果追加的元素數量超過了原切片容量,那么最后返回的是一個全新數組中的全新切片。如果沒有超過,那么最后返回的是原數組中的全新切片。無論如何,append對原切片無任何影響。如下示例:

復制代碼代碼如下:

func test12() {

slice := []int32{1, 2, 3, 4, 5, 6}

slice2 := slice[:2]

_ = append(slice2, 50, 60, 70, 80, 90)

fmt.Printf("slice為:%v\n", slice)

fmt.Printf("操作的切片:%v\n", slice2)

_ = append(slice2, 50, 60)

fmt.Printf("slice為:%v\n", slice)

fmt.Printf("操作的切片:%v\n", slice2)

}

如上,append方法用了2次,結果返回的結果完全不同,原因是第二次append方法追加的元素數量沒有超過 slice 的容量。而無論怎樣,原切片slice2都無影響。結果:

slice為:[1 2 3 4 5 6]

操作的切片:[1 2]

slice為:[1 2 50 60 5 6]

操作的切片:[1 2]

Golang 中數組(Array)和切片(Slice)的區別

Go 中數組的長度是不可改變的,而 Slice 解決的就是對不定長數組的需求。他們的區別主要有兩點。

數組:

切片:

注意 1

雖然數組在初始化時也可以不指定長度,但 Go 語言會根據數組中元素個數自動設置數組長度,并且不可改變。切片通過 append 方法增加元素:

如果將 append 用在數組上,你將會收到報錯:first argument to append must be slice。

注意 2

切片不只有長度(len)的概念,同時還有容量(cap)的概念。因此切片其實還有一個指定長度和容量的初始化方式:

這就初始化了一個長度為3,容量為5的切片。

此外,切片還可以從一個數組中初始化(可應用于如何將數組轉換成切片):

上述例子通過數組 a 初始化了一個切片 s。

當切片和數組作為參數在函數(func)中傳遞時,數組傳遞的是值,而切片傳遞的是指針。因此當傳入的切片在函數中被改變時,函數外的切片也會同時改變。相同的情況,函數外的數組則不會發生任何變化。

golang 新人求助:關于切片截取的問題

"切完不延切片平面整齊切下" 啥意思。。。 我一般使用切邊 是點級別切割 使用XYZ數值移動 旋轉 或者捕捉 這樣確定方位是比較精準的。

Go語言 排序與搜索切片

Go語言標準庫中提供了sort包對整型,浮點型,字符串型切片進行排序,檢查一個切片是否排好序,使用二分法搜索函數在一個有序切片中搜索一個元素等功能。

關于sort包內的函數說明與使用,請查看

在這里簡單講幾個sort包中常用的函數

在Go語言中,對字符串的排序都是按照字節排序,也就是說在對字符串排序時是區分大小寫的。

二分搜索算法

Go語言中提供了一個使用二分搜索算法的sort.Search(size,fn)方法:每次只需要比較㏒?n個元素,其中n為切片中元素的總數。

sort.Search(size,fn)函數接受兩個參數:所處理的切片的長度和一個將目標元素與有序切片的元素相比較的函數,該函數是一個閉包,如果該有序切片是升序排列,那么在判斷時使用 有序切片的元素 = 目標元素。該函數返回一個int值,表示與目標元素相同的切片元素的索引。

在切片中查找出某個與目標字符串相同的元素索引

Go切片數組深度解析

Go 中的分片數組,實際上有點類似于Java中的ArrayList,是一個可以擴展的數組,但是Go中的切片由比較靈活,它和數組很像,也是基于數組,所以在了解Go切片前我們先了解下數組。

數組簡單描述就由相同類型元素組成的數據結構, 在創建初期就確定了長度,是不可變的。

但是Go的數組類型又和C與Java的數組類型不一樣, NewArray 用于創建一個數組,從源碼中可以看出最后返回的是 Array{}的指針,并不是第一個元素的指針,在Go中數組屬于值類型,在進行傳遞時,采取的是值傳遞,通過拷貝整個數組。Go語言的數組是一種有序的struct。

Go 語言的數組有兩種不同的創建方式,一種是顯示的初始化,一種是隱式的初始化。

注意一定是使用 [...]T 進行創建,使用三個點的隱式創建,編譯器會對數組的大小進行推導,只是Go提供的一種語法糖。

其次,Go中數組的類型,是由數值類型和長度兩個一起確定的。[2]int 和 [3]int 不是同一個類型,不能進行傳參和比較,把數組理解為類型和長度兩個屬性的結構體,其實就一目了然了。

Go中的數組屬于值類型,通常應該存儲于棧中,局部變量依然會根據逃逸分析確定存儲棧還是堆中。

編譯器對數組函數中做兩種不同的優化:

在靜態區完成賦值后復制到棧中。

總結起來,在不考慮逃逸分析的情況下,如果數組中元素的個數小于或者等于 4 個,那么所有的變量會直接在棧上初始化,如果數組元素大于 4 個,變量就會在靜態存儲區初始化然后拷貝到棧上。

由于數組是值類型,那么賦值和函數傳參操作都會復制整個數組數據。

不管是賦值或函數傳參,地址都不一致,發生了拷貝。如果數組的數據較大,則會消耗掉大量內存。那么為了減少拷貝我們可以主動的傳遞指針呀。

地址是一樣的,不過傳指針會有一個弊端,從打印結果可以看到,指針地址都是同一個,萬一原數組的指針指向更改了,那么函數里面的指針指向都會跟著更改。

同樣的我們將數組轉換為切片,通過傳遞切片,地址是不一樣的,數組值相同。

切片是引用傳遞,所以它們不需要使用額外的內存并且比使用數組更有效率。

所以,切片屬于引用類型。

通過這種方式可以將數組轉換為切片。

中間不加三個點就是切片,使用這種方式創建切片,實際上是先創建數組,然后再通過第一種方式創建。

使用make創建切片,就不光編譯期了,make創建切片會涉及到運行期。1. 切片的大小和容量是否足夠??;

切片是否發生了逃逸,最終在堆上初始化。如果切片小的話會先在?;蜢o態區進行創建。

切片有一個數組的指針,len是指切片的長度, cap指的是切片的容量。

cap是在初始化切片是生成的容量。

發現切片的結構體是數組的地址指針array unsafe.Pointer,而Go中數組的地址代表數組結構體的地址。

slice 中得到一塊內存地址,array[0]或者unsafe.Pointer(array[0])。

也可以通過地址構造切片

nil切片:指的unsafe.Pointer 為nil

空切片:

創建的指針不為空,len和cap為空

當一個切片的容量滿了,就需要擴容了。怎么擴,策略是什么?

如果原來數組切片的容量已經達到了最大值,再想擴容, Go 默認會先開一片內存區域,把原來的值拷貝過來,然后再執行 append() 操作。這種情況對現數組的地址和原數組地址不相同。

從上面結果我們可以看到,如果用 range 的方式去遍歷一個切片,拿到的 Value 其實是切片里面的值拷貝,即淺拷貝。所以每次打印 Value 的地址都不變。

由于 Value 是值拷貝的,并非引用傳遞,所以直接改 Value 是達不到更改原切片值的目的的,需要通過 slice[index] 獲取真實的地址。

分享題目:go語言怎么定義切片 go切片操作
轉載注明:http://m.kartarina.com/article14/hgeege.html

成都網站建設公司_創新互聯,為您提供企業建站、建站公司、網站導航、外貿建站、網站制作、小程序開發

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

成都定制網站網頁設計
主站蜘蛛池模板: 不卡无码人妻一区三区音频| 亚洲中文字幕无码永久在线| 无码精品A∨在线观看十八禁| 久久无码中文字幕东京热| 无码精品一区二区三区| 国产色爽免费无码视频| 97无码免费人妻超级碰碰碰碰| 东京热无码av一区二区 | 性无码一区二区三区在线观看| 小13箩利洗澡无码视频网站| 国产成人无码网站| 亚洲国产超清无码专区| 日韩人妻无码一区二区三区 | 人妻少妇看A偷人无码精品视频| 中文无码AV一区二区三区| 无遮掩无码h成人av动漫| 日韩精品无码一区二区中文字幕| 色综合热无码热国产| 亚洲heyzo专区无码综合| 无码人妻精品一区二区三区99仓本 | 亚洲中文字幕无码久久精品1| 国产精品成人99一区无码| 久久亚洲精品无码av| 中文字幕乱偷无码av先锋蜜桃| 在线观看免费无码专区| 永久免费av无码入口国语片| 久久精品无码一区二区app| 亚洲a无码综合a国产av中文 | 精品久久无码中文字幕| 无码av免费一区二区三区试看| 一本一道AV无码中文字幕| 亚洲桃色AV无码| 久久久久无码国产精品一区| 亚洲国产精品无码av| 亚洲午夜国产精品无码 | 精品人体无码一区二区三区| 日产无码1区2区在线观看| 久久99久久无码毛片一区二区| 亚洲国产精品无码久久九九 | 伊人久久无码中文字幕| 亚洲gv猛男gv无码男同短文|