What is the difference between arrays and slices in go language?
The difference between arrays and slices: 1. Slices are pointer types, arrays are value types; 2. The assignment form of arrays is value transfer, and the assignment form of slices is reference transfer; 3. The length of the array is fixed , and the slice length can be adjusted arbitrarily (the slice is a dynamic array); 4. The length of the array is fixed, but the slice length can be adjusted arbitrarily (the slice is a dynamic array).
The operating environment of this tutorial: Windows 7 system, GO version 1.18, Dell G3 computer.
The array in Go language is roughly equivalent to the array in C/C, with a fixed size and cannot be dynamically expanded in size, while the slice is roughly equivalent to the Vector in C, which can be dynamically expanded in size , when the size exceeds the capacity, reallocate a piece of memory, and then copy the data to the new memory area. Let's go through a few questions to better understand golang's arrays and slices. Let's take a look.
1. Array
Go's slice is an abstract data type on top of the array, so you must first understand the array before understanding the slice .
1. Three ways to declare arrays
- var identifier [len]type
- var identifier = [len]type{value1 , value2, … , valueN}
- var identifier = […]type{value1, value2, … , valueN}
Corresponding:
- identifier := [len]type{}
- identifier := [len]type{value1, value2, … , valueN}
- identifier := […]type{value1, value2, …, valueN}
Example:
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)
Result:
[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]]
We look at the array iarray1, which is only declared and not assigned. The Go language helps us automatically assign the value as 0. Looking at iarray2 and iarray3 again, we can see that the Go language declaration can indicate the type or not. var iarray3 = [5]int32{1, 2, 3, 4, 5} is also completely fine.
2. The capacity and length of the array
The capacity and length of the array are the same. Both the cap() function and the len() function output the capacity (i.e. length) of the array
3. Type
Arrays are value types. When assigning one array to another array, the passed It's a copy. While slices are reference types, the array wrapped by the slice is called the underlying array of the slice. Look at the following example:
//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]
2. Slicing
In Go language, a slice is an identical sequence of elements with variable length and fixed capacity. The essence of slice in Go language is an array. The capacity is fixed because the length of the array is fixed, and the capacity of the slice is the length of the hidden array. Variable length refers to being variable within the range of the array length.
1. Four ways to create slices
- var slice1 = make([]int,5,10)
- var slice2 = make([]int,5)
- var slice3 = []int{}
- var slice4 = []int{1,2,3,4,5}
Correspondingly:
- slice1 := make([]int,5,10)
- slice2 := make([]int,5)
- slice3 := []int{}
- slice4 := []int{1,2,3,4,5}
The corresponding output of the above
[0 0 0 0 0] [0 0 0 0 0] [] [1 2 3 4 5]
It can be seen from 3) and 4) that the only difference between creating a slice and creating an array is whether there is a number in the "[]" before Type. If it is empty, it represents a slice, otherwise it represents an array. Because slices are of variable length
2. Hidden array
Go's slice is an abstract data type on top of the array, so the created slice always has a The array exists.
Example:
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)
Output:
[a b c d e] [c d] [a b c] [a b 8 d e] [8 d] [a b 8]
It also shows that slices slice0, slice1 and slice2 are references to the same underlying array, so slice2 has changed, and the other two It will all change
3. append appends the slice
The built-in function append can append one or more other values of the same type to a slice. If the number of appended elements exceeds the capacity of the original slice, what is finally returned is a brand new slice in a brand new array. If it does not exceed, then what is finally returned is a brand new slice in the original array. In any case, append has no effect on the original slice.
Example:
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]) }
Output:
2 5 //长度和容量 0xc420012150 0xc420012158 3 5 //第一次追加,未超出容量,所以内存地址未发生改变 0xc420012150 0xc420012158 0xc420012160 6 10 //第二次追加,超过容量,内存地址都发生了改变,且容量也发生了改变,且是原来的2倍 0xc4200100f0 0xc4200100f8 0xc420010100 0xc420010108 0xc420010110 0xc420010118
Look at another example:
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]) }
The above output:
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
3. GO The difference between arrays and slices
The following mainly looks at some practical examples to illustrate the difference between arrays and slices.
1. Assignment forms of arrays and slices
Example 1
arr1 := [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
As can be seen from this example, array The assignment is a copy of the value, which is a brand new array. The assignment of the slice is a reference . Let’s look at another example.
Example 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]
This example once again illustrates: arrays are assignments and copies, while slices are only references. The slice declarations in Examples 1 and 2 use hidden arrays. Let's look at Example 3 again, using a non-hidden array.
Example 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 0xc42001216
To sum up the above three examples, it can be seen that slices are references to arrays, including references to hidden arrays and non-hidden arrays.
2. The array is used as a parameter and is called by the function
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)属性
The above is the detailed content of What is the difference between arrays and slices in go language?. For more information, please follow other related articles on the PHP Chinese website!

Golang is more suitable for high concurrency tasks, while Python has more advantages in flexibility. 1.Golang efficiently handles concurrency through goroutine and channel. 2. Python relies on threading and asyncio, which is affected by GIL, but provides multiple concurrency methods. The choice should be based on specific needs.

The performance differences between Golang and C are mainly reflected in memory management, compilation optimization and runtime efficiency. 1) Golang's garbage collection mechanism is convenient but may affect performance, 2) C's manual memory management and compiler optimization are more efficient in recursive computing.

ChooseGolangforhighperformanceandconcurrency,idealforbackendservicesandnetworkprogramming;selectPythonforrapiddevelopment,datascience,andmachinelearningduetoitsversatilityandextensivelibraries.

Golang and Python each have their own advantages: Golang is suitable for high performance and concurrent programming, while Python is suitable for data science and web development. Golang is known for its concurrency model and efficient performance, while Python is known for its concise syntax and rich library ecosystem.

In what aspects are Golang and Python easier to use and have a smoother learning curve? Golang is more suitable for high concurrency and high performance needs, and the learning curve is relatively gentle for developers with C language background. Python is more suitable for data science and rapid prototyping, and the learning curve is very smooth for beginners.

Golang and C each have their own advantages in performance competitions: 1) Golang is suitable for high concurrency and rapid development, and 2) C provides higher performance and fine-grained control. The selection should be based on project requirements and team technology stack.

Golang is suitable for rapid development and concurrent programming, while C is more suitable for projects that require extreme performance and underlying control. 1) Golang's concurrency model simplifies concurrency programming through goroutine and channel. 2) C's template programming provides generic code and performance optimization. 3) Golang's garbage collection is convenient but may affect performance. C's memory management is complex but the control is fine.

Goimpactsdevelopmentpositivelythroughspeed,efficiency,andsimplicity.1)Speed:Gocompilesquicklyandrunsefficiently,idealforlargeprojects.2)Efficiency:Itscomprehensivestandardlibraryreducesexternaldependencies,enhancingdevelopmentefficiency.3)Simplicity:


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

SublimeText3 Linux new version
SublimeText3 Linux latest version

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.