數(shù)組是一個(gè)由 固定長(zhǎng)度 的 特定類(lèi)型元素 組成的序列,一個(gè)數(shù)組可以由零個(gè)或多個(gè)元素組成。 數(shù)組是值類(lèi)型
丘北ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書(shū)未來(lái)市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)的ssl證書(shū)銷(xiāo)售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18982081108(備注:SSL證書(shū)合作)期待與您的合作!
數(shù)組的每個(gè)元素都可以通過(guò)索引下標(biāo)來(lái)訪問(wèn),索引下標(biāo)的范圍是從0開(kāi)始到數(shù)組長(zhǎng)度減1的位置,內(nèi)置函數(shù) len() 可以返回?cái)?shù)組中元素的個(gè)數(shù)。
2.類(lèi)型的打印,結(jié)果的第二種打印方式
3.對(duì)元素的修改或者賦值
4.判斷數(shù)組是否相等:長(zhǎng)度、類(lèi)型
4.數(shù)組的地址:連續(xù)存儲(chǔ)的空間
5.數(shù)組的賦值、地址、取值
6.數(shù)組的默認(rèn)值
7.數(shù)組的初始化
8.數(shù)組的逆置
9.求數(shù)組的最大值、最小值、平均值
10.對(duì)數(shù)組字符串進(jìn)行連接
11.冒泡排序法的實(shí)現(xiàn)
12.數(shù)組做函數(shù)的參數(shù)
13.二維數(shù)組:賦值和地址
14.二維數(shù)組:打印和輸出
15. 指針數(shù)組,每一個(gè)元素都是地址
17.數(shù)組的內(nèi)存分配
Go 中的分片數(shù)組,實(shí)際上有點(diǎn)類(lèi)似于Java中的ArrayList,是一個(gè)可以擴(kuò)展的數(shù)組,但是Go中的切片由比較靈活,它和數(shù)組很像,也是基于數(shù)組,所以在了解Go切片前我們先了解下數(shù)組。
數(shù)組簡(jiǎn)單描述就由相同類(lèi)型元素組成的數(shù)據(jù)結(jié)構(gòu), 在創(chuàng)建初期就確定了長(zhǎng)度,是不可變的。
但是Go的數(shù)組類(lèi)型又和C與Java的數(shù)組類(lèi)型不一樣, NewArray 用于創(chuàng)建一個(gè)數(shù)組,從源碼中可以看出最后返回的是 Array{}的指針,并不是第一個(gè)元素的指針,在Go中數(shù)組屬于值類(lèi)型,在進(jìn)行傳遞時(shí),采取的是值傳遞,通過(guò)拷貝整個(gè)數(shù)組。Go語(yǔ)言的數(shù)組是一種有序的struct。
Go 語(yǔ)言的數(shù)組有兩種不同的創(chuàng)建方式,一種是顯示的初始化,一種是隱式的初始化。
注意一定是使用 [...]T 進(jìn)行創(chuàng)建,使用三個(gè)點(diǎn)的隱式創(chuàng)建,編譯器會(huì)對(duì)數(shù)組的大小進(jìn)行推導(dǎo),只是Go提供的一種語(yǔ)法糖。
其次,Go中數(shù)組的類(lèi)型,是由數(shù)值類(lèi)型和長(zhǎng)度兩個(gè)一起確定的。[2]int 和 [3]int 不是同一個(gè)類(lèi)型,不能進(jìn)行傳參和比較,把數(shù)組理解為類(lèi)型和長(zhǎng)度兩個(gè)屬性的結(jié)構(gòu)體,其實(shí)就一目了然了。
Go中的數(shù)組屬于值類(lèi)型,通常應(yīng)該存儲(chǔ)于棧中,局部變量依然會(huì)根據(jù)逃逸分析確定存儲(chǔ)棧還是堆中。
編譯器對(duì)數(shù)組函數(shù)中做兩種不同的優(yōu)化:
在靜態(tài)區(qū)完成賦值后復(fù)制到棧中。
總結(jié)起來(lái),在不考慮逃逸分析的情況下,如果數(shù)組中元素的個(gè)數(shù)小于或者等于 4 個(gè),那么所有的變量會(huì)直接在棧上初始化,如果數(shù)組元素大于 4 個(gè),變量就會(huì)在靜態(tài)存儲(chǔ)區(qū)初始化然后拷貝到棧上。
由于數(shù)組是值類(lèi)型,那么賦值和函數(shù)傳參操作都會(huì)復(fù)制整個(gè)數(shù)組數(shù)據(jù)。
不管是賦值或函數(shù)傳參,地址都不一致,發(fā)生了拷貝。如果數(shù)組的數(shù)據(jù)較大,則會(huì)消耗掉大量?jī)?nèi)存。那么為了減少拷貝我們可以主動(dòng)的傳遞指針呀。
地址是一樣的,不過(guò)傳指針會(huì)有一個(gè)弊端,從打印結(jié)果可以看到,指針地址都是同一個(gè),萬(wàn)一原數(shù)組的指針指向更改了,那么函數(shù)里面的指針指向都會(huì)跟著更改。
同樣的我們將數(shù)組轉(zhuǎn)換為切片,通過(guò)傳遞切片,地址是不一樣的,數(shù)組值相同。
切片是引用傳遞,所以它們不需要使用額外的內(nèi)存并且比使用數(shù)組更有效率。
所以,切片屬于引用類(lèi)型。
通過(guò)這種方式可以將數(shù)組轉(zhuǎn)換為切片。
中間不加三個(gè)點(diǎn)就是切片,使用這種方式創(chuàng)建切片,實(shí)際上是先創(chuàng)建數(shù)組,然后再通過(guò)第一種方式創(chuàng)建。
使用make創(chuàng)建切片,就不光編譯期了,make創(chuàng)建切片會(huì)涉及到運(yùn)行期。1. 切片的大小和容量是否足夠??;
切片是否發(fā)生了逃逸,最終在堆上初始化。如果切片小的話會(huì)先在?;蜢o態(tài)區(qū)進(jìn)行創(chuàng)建。
切片有一個(gè)數(shù)組的指針,len是指切片的長(zhǎng)度, cap指的是切片的容量。
cap是在初始化切片是生成的容量。
發(fā)現(xiàn)切片的結(jié)構(gòu)體是數(shù)組的地址指針array unsafe.Pointer,而Go中數(shù)組的地址代表數(shù)組結(jié)構(gòu)體的地址。
slice 中得到一塊內(nèi)存地址,array[0]或者unsafe.Pointer(array[0])。
也可以通過(guò)地址構(gòu)造切片
nil切片:指的unsafe.Pointer 為nil
空切片:
創(chuàng)建的指針不為空,len和cap為空
當(dāng)一個(gè)切片的容量滿了,就需要擴(kuò)容了。怎么擴(kuò),策略是什么?
如果原來(lái)數(shù)組切片的容量已經(jīng)達(dá)到了最大值,再想擴(kuò)容, Go 默認(rèn)會(huì)先開(kāi)一片內(nèi)存區(qū)域,把原來(lái)的值拷貝過(guò)來(lái),然后再執(zhí)行 append() 操作。這種情況對(duì)現(xiàn)數(shù)組的地址和原數(shù)組地址不相同。
從上面結(jié)果我們可以看到,如果用 range 的方式去遍歷一個(gè)切片,拿到的 Value 其實(shí)是切片里面的值拷貝,即淺拷貝。所以每次打印 Value 的地址都不變。
由于 Value 是值拷貝的,并非引用傳遞,所以直接改 Value 是達(dá)不到更改原切片值的目的的,需要通過(guò) slice[index] 獲取真實(shí)的地址。
數(shù)組
數(shù)組是內(nèi)置(build-in)類(lèi)型,是一組同類(lèi)型數(shù)據(jù)的集合。
數(shù)組的初始化有多種形式
長(zhǎng)度為5的數(shù)組,其元素值依次為:1,2,3,4,5
長(zhǎng)度為5的數(shù)組,其元素值依次為:1,2,0,0,0 。在初始化時(shí)沒(méi)有指定初值的元素將會(huì)賦值為其元素類(lèi)型int的默認(rèn)值0,string的默認(rèn)值是 ""
長(zhǎng)度為5的數(shù)組,其長(zhǎng)度是根據(jù)初始化時(shí)指定的元素個(gè)數(shù)決定的
長(zhǎng)度為5的數(shù)組,key:value,其元素值依次為:0,0,1,2,3。在初始化時(shí)指定了2,3,4索引中對(duì)應(yīng)的值:1,2,3
長(zhǎng)度為5的數(shù)組,起元素值依次為:0,0,1,0,3。由于指定了最大索引4對(duì)應(yīng)的值3,根據(jù)初始化的元素個(gè)數(shù)確定其長(zhǎng)度為5
切片
數(shù)組的長(zhǎng)度不可改變,在特定場(chǎng)景中這樣的集合就不太適用,Go中提供了一種靈活,功能強(qiáng)悍的內(nèi)置類(lèi)型 Slices 切片。
切片可以通過(guò)數(shù)組來(lái)初始化,也可以通過(guò)內(nèi)置函數(shù)make()初始化。初始化時(shí)len=cap,在追加元素時(shí)如果容量cap不足時(shí)將按len的 2 倍擴(kuò)容。
直接初始化切片, [] 表示是切片類(lèi)型, {1,2,3} 初始化值依次是1,2,3.其cap=len=3
初始化切片s,是數(shù)組arr的引用
將arr中從下標(biāo)startIndex到endIndex-1 下的元素 創(chuàng)建為一個(gè)新的切片
缺省endIndex時(shí)將表示一直到arr的最后一個(gè)元素
缺省startIndex時(shí)將表示從arr的第一個(gè)元素開(kāi)始
通過(guò)切片s初始化切片s1
通過(guò)內(nèi)置函數(shù)make()初始化切片s,[]int 標(biāo)識(shí)為其元素類(lèi)型為int的切片
在go語(yǔ)言中 new() 這是一個(gè)用來(lái)分配內(nèi)存的內(nèi)置函數(shù),它的第一個(gè)參數(shù)是一個(gè)類(lèi)型,不是一個(gè)值,它的返回值是一個(gè)指向新分配的 t 類(lèi)型的零值的指針。
在golang的代碼定義如下: func new(t Type) *Type strut{} 直接使用struct{} 來(lái)初始化strut時(shí),返回的是一個(gè)struct類(lèi)型的值,而不是指針兩者是不一樣的 兩者對(duì)比代碼如下:
type Student struct{ id int name string } func main(){ var s_1 *Student = new(Student) s_1.id = 100 s_1.name = "cat"
var s_2 Student = Student{id:1,name:"tom"} fmt.Println(s_1,s_2) } 輸出結(jié)果:
{100 cat} {1 tom} 從上面代碼的聲明和打印的結(jié)果中就可以看出 s_1 的類(lèi)型為指針,s_2 為一個(gè)Student類(lèi)型
本教程介紹 Go 中多模塊工作區(qū)的基礎(chǔ)知識(shí)。使用多模塊工作區(qū),您可以告訴 Go 命令您正在同時(shí)在多個(gè)模塊中編寫(xiě)代碼,并輕松地在這些模塊中構(gòu)建和運(yùn)行代碼。
在本教程中,您將在共享的多模塊工作區(qū)中創(chuàng)建兩個(gè)模塊,對(duì)這些模塊進(jìn)行更改,并在構(gòu)建中查看這些更改的結(jié)果。
本教程需要 go1.18 或更高版本。使用go.dev/dl中的鏈接確保您已在 Go 1.18 或更高版本中安裝了 Go 。
首先,為您要編寫(xiě)的代碼創(chuàng)建一個(gè)模塊。
1、打開(kāi)命令提示符并切換到您的主目錄。
在 Linux 或 Mac 上:
在 Windows 上:
2、在命令提示符下,為您的代碼創(chuàng)建一個(gè)名為工作區(qū)的目錄。
3、初始化模塊
我們的示例將創(chuàng)建一個(gè)hello依賴(lài)于 golang.org/x/example 模塊的新模塊。
創(chuàng)建你好模塊:
使用 . 添加對(duì) golang.org/x/example 模塊的依賴(lài)項(xiàng)go get。
在 hello 目錄下創(chuàng)建 hello.go,內(nèi)容如下:
現(xiàn)在,運(yùn)行 hello 程序:
在這一步中,我們將創(chuàng)建一個(gè)go.work文件來(lái)指定模塊的工作區(qū)。
在workspace目錄中,運(yùn)行:
該go work init命令告訴為包含目錄中模塊的工作空間go創(chuàng)建一個(gè)文件 。go.work./hello
該go命令生成一個(gè)go.work如下所示的文件:
該go.work文件的語(yǔ)法與go.mod相同。
該go指令告訴 Go 應(yīng)該使用哪個(gè)版本的 Go 來(lái)解釋文件。它類(lèi)似于文件中的go指令go.mod 。
該use指令告訴 Go在進(jìn)行構(gòu)建時(shí)hello目錄中的模塊應(yīng)該是主模塊。
所以在模塊的任何子目錄中workspace都會(huì)被激活。
2、運(yùn)行工作區(qū)目錄下的程序
在workspace目錄中,運(yùn)行:
Go 命令包括工作區(qū)中的所有模塊作為主模塊。這允許我們?cè)谀K中引用一個(gè)包,即使在模塊之外。在模塊或工作區(qū)之外運(yùn)行g(shù)o run命令會(huì)導(dǎo)致錯(cuò)誤,因?yàn)樵揼o命令不知道要使用哪些模塊。
接下來(lái),我們將golang.org/x/example模塊的本地副本添加到工作區(qū)。然后,我們將向stringutil包中添加一個(gè)新函數(shù),我們可以使用它來(lái)代替Reverse.
在這一步中,我們將下載包含該模塊的 Git 存儲(chǔ)庫(kù)的副本golang.org/x/example,將其添加到工作區(qū),然后向其中添加一個(gè)我們將從 hello 程序中使用的新函數(shù)。
1、克隆存儲(chǔ)庫(kù)
在工作區(qū)目錄中,運(yùn)行g(shù)it命令來(lái)克隆存儲(chǔ)庫(kù):
2、將模塊添加到工作區(qū)
該go work use命令將一個(gè)新模塊添加到 go.work 文件中。它現(xiàn)在看起來(lái)像這樣:
該模塊現(xiàn)在包括example.com/hello模塊和 `golang.org/x/example 模塊。
這將允許我們使用我們將在模塊副本中編寫(xiě)的新代碼,而不是使用命令stringutil下載的模塊緩存中的模塊版本。
3、添加新功能。
我們將向golang.org/x/example/stringutil包中添加一個(gè)新函數(shù)以將字符串大寫(xiě)。
將新文件夾添加到workspace/example/stringutil包含以下內(nèi)容的目錄:
4、修改hello程序以使用該功能。
修改workspace/hello/hello.go的內(nèi)容以包含以下內(nèi)容:
從工作區(qū)目錄,運(yùn)行
Go 命令在go.work文件指定的hello目錄中查找命令行中指定的example.com/hello模塊 ,同樣使用go.work文件解析導(dǎo)入golang.org/x/example。
go.work可以用來(lái)代替添加replace 指令以跨多個(gè)模塊工作。
由于這兩個(gè)模塊在同一個(gè)工作區(qū)中,因此很容易在一個(gè)模塊中進(jìn)行更改并在另一個(gè)模塊中使用它。
現(xiàn)在,要正確發(fā)布這些模塊,我們需要發(fā)布golang.org/x/example 模塊,例如在v0.1.0. 這通常通過(guò)在模塊的版本控制存儲(chǔ)庫(kù)上標(biāo)記提交來(lái)完成。發(fā)布完成后,我們可以增加對(duì) golang.org/x/example模塊的要求hello/go.mod:
這樣,該go命令可以正確解析工作區(qū)之外的模塊。