Heim > Artikel > Backend-Entwicklung > Was ist der Unterschied zwischen Arrays und Slices in der Go-Sprache?
Der Unterschied zwischen Arrays und Slices: 1. Slices sind Zeigertypen, Arrays sind Werttypen; 2. Die Zuweisungsform von Arrays ist die Wertübertragung und die Zuweisungsform von Slices ist die Referenzübertragung. 3. Die Länge von Arrays ist festgelegt , während die Länge der Slices beliebig angepasst werden kann (Slices sind dynamische Arrays); 4. Die Länge des Arrays ist fest, aber die Slice-Länge kann beliebig angepasst werden (Slices sind dynamische Arrays).
Die Betriebsumgebung dieses Tutorials: Windows 7-System, GO Version 1.18, Dell G3-Computer.
Arrays in der Go-Sprache entsprechen in etwa den Arrays in C/C++. Sie haben eine feste Größe und können nicht dynamisch erweitert werden. Das Slicing entspricht in etwa dem Vektor in C++, dessen Größe dynamisch erweitert werden kann Wenn die Kapazität zu hoch ist, wird ein Speicherblock neu zugewiesen und die Daten in den neuen Speicherbereich kopiert. Lassen Sie uns ein paar Fragen durchgehen, um die Arrays und Slices von Golang besser zu verstehen.
Gos Slice ist ein abstrakter Datentyp über dem Array. Sie müssen also zuerst das Array verstehen, bevor Sie das Slice verstehen.
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]]
Die Kapazität und Länge des Arrays sind gleich. Sowohl die Funktion cap() als auch die Funktion len() geben die Kapazität (d. h. die Länge) des Arrays aus
3. Bei der Zuweisung eines Arrays zu einem anderen Array wird eine Kopie übergeben. Während es sich bei Slices um Referenztypen handelt, wird das vom Slice umschlossene Array als das zugrunde liegende Array des Slice bezeichnet. Schauen Sie sich das folgende Beispiel an:
//a是一个数组,注意数组是一个固定长度的,初始化时候必须要指定长度,不指定长度的话就是切片了 a := [3]int{1, 2, 3} //b是数组,是a的一份拷贝 b := a //c是切片,是引用类型,底层数组是a c := a[:] for i := 0; i < len(a); i++ { a[i] = a[i] + 1 } //改变a的值后,b是a的拷贝,b不变,c是引用,c的值改变 fmt.Println(a) //[2,3,4] fmt.Println(b) //[1 2 3] fmt.Println(c) //[2,3,4]
In der Go-Sprache ist ein Slice eine identische Folge von Elementen mit variabler Länge und fester Kapazität. Die Essenz von Slice in der Go-Sprache ist ein Array. Die Kapazität ist fest, da die Länge des Arrays fest ist und die Kapazität des Slice der Länge des verborgenen Arrays entspricht. Variable Länge bedeutet, dass sie innerhalb des Bereichs der Array-Länge variabel ist.
1. Vier Möglichkeiten, Slices zu erstellen[0 0 0 0 0] [0 0 0 0 0] [] [1 2 3 4 5]
Beispiel:
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)
Ausgabe:
[a b c d e] [c d] [a b c] [a b 8 d e] [8 d] [a b 8]
Die integrierte Funktion append kann einen oder mehrere andere Werte desselben Typs an ein Slice anhängen. Wenn die Anzahl der angehängten Elemente die Kapazität des ursprünglichen Slice überschreitet, wird letztendlich ein brandneuer Slice in einem brandneuen Array zurückgegeben. Wenn der Wert nicht überschritten wird, wird letztendlich ein brandneues Slice im ursprünglichen Array zurückgegeben. In jedem Fall hat das Anhängen keine Auswirkung auf das Original-Slice. Beispiel:
slice1 := make([]int, 2, 5) fmt.Println(len(slice1), cap(slice1)) for k := range slice1{ fmt.Println(&slice1[k]) } slice1 = append(slice1,4) fmt.Println(len(slice1), cap(slice1)) for k := range slice1{ fmt.Println(&slice1[k]) } slice1 = append(slice1,5,6,7) fmt.Println(len(slice1), cap(slice1)) for k := range slice1{ fmt.Println(&slice1[k]) }Ausgabe:
2 5 //长度和容量 0xc420012150 0xc420012158 3 5 //第一次追加,未超出容量,所以内存地址未发生改变 0xc420012150 0xc420012158 0xc420012160 6 10 //第二次追加,超过容量,内存地址都发生了改变,且容量也发生了改变,且是原来的2倍 0xc4200100f0 0xc4200100f8 0xc420010100 0xc420010108 0xc420010110 0xc420010118Sehen Sie sich ein anderes Beispiel an:
slice1 := make([]int, 2, 5) slice2 := slice1[:1] fmt.Println(len(slice1), cap(slice1)) for k := range slice1{ fmt.Println(&slice1[k]) } fmt.Println(len(slice2), cap(slice2)) for k := range slice2{ fmt.Println(&slice2[k]) } slice2 = append(slice2,4,5,6,7,8) fmt.Println(len(slice1), cap(slice1)) for k := range slice1{ fmt.Println(&slice1[k]) } fmt.Println(len(slice2), cap(slice2)) for k := range slice2{ fmt.Println(&slice2[k]) }Die obige Ausgabe:
2 5 //slice1的长度和容量 0xc4200700c0 0xc4200700c8 1 5 //slice2的长度和容量 0xc4200700c0 2 5 //slice2追加后,slice1的长度和容量、内存都未发生改变 0xc4200700c0 0xc4200700c8 6 10 //slice2追加后,超过了容量,所以slice2的长度和容量、内存地址都发生改变。 0xc42007e000 0xc42007e008 0xc42007e010 0xc42007e018 0xc42007e020 0xc42007e028
1. Zuweisungsformen von Arrays und Slices
Beispiel 1arr1 := [3] int {1,2,3} arr2 := arr1 for k := range arr1 { fmt.Printf("%v ",&arr1[k]); } fmt.Println(""); for k := range arr2 { fmt.Printf("%v ",&arr2[k]); } fmt.Println("\n================="); slice1 := [] int{1,2,3} slice2 := slice1 for k := range slice1 { fmt.Printf("%v ",&slice1[k]); } fmt.Println(""); for k := range slice2 { fmt.Printf("%v ",&slice2[k]); } 输出结果: 0xc420014140 0xc420014148 0xc420014150 0xc420014160 0xc420014168 0xc420014170 ================= 0xc4200141a0 0xc4200141a8 0xc4200141b0 0xc4200141a0 0xc4200141a8 0xc4200141b0
. Schauen wir uns ein anderes Beispiel an.
Beispiel 2:
arr1 := [3] int {1,2,3} arr2 := arr1 fmt.Printf("%v %v ",arr1,arr2); arr1[0] = 11 arr2[1] = 22 fmt.Printf("\n%v %v ",arr1,arr2); fmt.Println("\n================"); slice1 := [] int{1,2,3} slice2 := slice1 fmt.Printf("%v %v ",slice1,slice2); slice1[0] = 11 slice2[1] = 22 fmt.Printf("\n%v %v ",slice1,slice2); 输出结果: [1 2 3] [1 2 3] [11 2 3] [1 22 3] ================ [1 2 3] [1 2 3] [11 22 3] [11 22 3]Dieses Beispiel verdeutlicht noch einmal: Arrays sind Zuweisungen und Kopien, während Slices nur Referenzen sind. Die Slice-Deklarationen in den Beispielen 1 und 2 verwenden versteckte Arrays. Schauen wir uns Beispiel 3 noch einmal an und verwenden dabei ein nicht ausgeblendetes Array.
Beispiel 3:
arr1 := [5] int {1,2,3} slice1 := arr1[0:3] slice2 := slice1[0:4] fmt.Printf("len: %d cap: %d %v\n",len(arr1),cap(arr1),arr1); //打印出非隐藏数组 for k := range arr1 { fmt.Printf("%v ",&arr1[k]); } fmt.Println(""); fmt.Printf("len: %d cap: %d %v\n",len(slice1),cap(slice1),slice1); //打印切片1 for k := range slice1 { fmt.Printf("%v ",&slice1[k]); } fmt.Println(""); fmt.Printf("len: %d cap: %d %v\n",len(slice2),cap(slice2),slice2); //打印切片2 for k := range slice2 { fmt.Printf("%v ",&slice2[k]); } fmt.Println("\n================="); arr1[0] = 11 //非隐藏数组、切片1、切片2各自发生更改 slice1[1] = 22 slice2[2] = 33 fmt.Printf("len: %d cap: %d %v\n",len(arr1),cap(arr1),arr1); //再次打印非隐藏数组 for k := range arr1 { fmt.Printf("%v ",&arr1[k]); } fmt.Println(""); fmt.Printf("len: %d cap: %d %v\n",len(slice1),cap(slice1),slice1); //再此打印切片1 for k := range slice1 { fmt.Printf("%v ",&slice1[k]); } fmt.Println(""); fmt.Printf("len: %d cap: %d %v\n",len(slice2),cap(slice2),slice2); //再次打印切片2 for k := range slice2 { fmt.Printf("%v ",&slice2[k]); } 输出结果: len: 5 cap: 5 [1 2 3 0 0]0xc420012150 0xc420012158 0xc420012160 0xc420012168 0xc420012170 len: 3 cap: 5 [1 2 3]0xc420012150 0xc420012158 0xc420012160 len: 4 cap: 5 [1 2 3 0]0xc420012150 0xc420012158 0xc420012160 0xc420012168 ================= len: 5 cap: 5 [11 22 33 0 0] 0xc420012150 0xc420012158 0xc420012160 0xc420012168 0xc420012170 len: 3 cap: 5 [11 22 33] 0xc420012150 0xc420012158 0xc420012160 len: 4 cap: 5 [11 22 33 0] 0xc420012150 0xc420012158 0xc420012160 0xc42001216Um die obigen drei Beispiele zusammenzufassen, ist ersichtlich, dass Slices Verweise auf Arrays sind, einschließlich Verweise auf versteckte Arrays und nicht versteckte Arrays.
2. Das Array wird als Parameter verwendet und von der Funktion aufgerufen
func Connect() { arr1 := [5] int {1,2,3} fmt.Printf("%v ",arr1); for k := range arr1 { fmt.Printf("%v ",&arr1[k]); } fmt.Println(""); f1(arr1) fmt.Println(""); f2(&arr1) } func f1(arr [5]int) { fmt.Printf("%v ",arr); for k := range arr { fmt.Printf("%v ",&arr[k]); } } func f2(arr *[5]int) { fmt.Printf("%v ",arr); for k := range arr { fmt.Printf("%v ",&arr[k]); } } 输出结果: [1 2 3 0 0] 0xc420012150 0xc420012158 0xc420012160 0xc420012168 0xc420012170 [1 2 3 0 0] 0xc4200121b0 0xc4200121b8 0xc4200121c0 0xc4200121c8 0xc4200121d0 &[1 2 3 0 0] 0xc420012150 0xc420012158 0xc420012160 0xc420012168 0xc420012170
从上面的例子可以看出,数组在参数中,可以使用值传递和引用传递。值传递会拷贝新数组,引用传递则使用原数组。
func Connect() { slice1 := [] int {1,2,3} fmt.Printf("%v ",slice1); for k := range slice1 { fmt.Printf("%v ",&slice1[k]); } fmt.Println(""); f1(slice1) } func f1(slice []int) { fmt.Printf("%v ",slice); for k := range slice { fmt.Printf("%v ",&slice[k]); } } 输出结果: [1 2 3] 0xc420014140 0xc420014148 0xc420014150 [1 2 3] 0xc420014140 0xc420014148 0xc42001415
从这个例子中可以看出,切片在参数中传递本身就引用。
总结:
切片是指针类型,数组是值类型
数组的赋值形式为值传递,切片的赋值形式为引用传递
数组的长度是固定的,而切片长度可以任意调整(切片是动态的数组)
数组只有长度一个属性,而切片比数组多了一个容量(cap)属性
Das obige ist der detaillierte Inhalt vonWas ist der Unterschied zwischen Arrays und Slices in der Go-Sprache?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!