Rumah >pembangunan bahagian belakang >Golang >Apakah perbezaan antara tatasusunan dan kepingan dalam bahasa go?

Apakah perbezaan antara tatasusunan dan kepingan dalam bahasa go?

青灯夜游
青灯夜游asal
2023-01-13 17:26:468273semak imbas

Perbezaan antara tatasusunan dan kepingan: 1. Slices ialah jenis penunjuk, tatasusunan ialah jenis nilai; daripada tatasusunan adalah tetap, dan panjang hirisan boleh dilaraskan sewenang-wenangnya (hirisan ialah tatasusunan dinamik 4. Panjang tatasusunan tetap, tetapi panjang hirisan boleh dilaraskan sewenang-wenangnya (hirisan ialah tatasusunan dinamik).

Apakah perbezaan antara tatasusunan dan kepingan dalam bahasa go?

Persekitaran pengendalian tutorial ini: sistem Windows 7, GO versi 1.18, komputer Dell G3.

Tatasusunan dalam bahasa Go hampir sama dengan tatasusunan dalam C/C++ saiznya tetap dan tidak boleh dikembangkan secara dinamik dalam saiz , apabila saiz melebihi kapasiti, agihkan semula sekeping memori, dan kemudian salin data ke kawasan ingatan baharu. Mari kita lihat beberapa soalan untuk lebih memahami tatasusunan dan kepingan golang. Mari kita lihat.

1 Tatasusunan

Kepingan Go ialah jenis data abstrak di atas tatasusunan, jadi anda mesti memahami tatasusunan dahulu sebelum memahami tatasusunan potong .

1. Tiga cara untuk mengisytiharkan tatasusunan

  • pengecam var [len]jenis
  • pengecam var = [len]jenis{value1 , value2, … , valueN}
  • var identifier = [...]type{value1, value2, … , valueN}

Sesuai:

  • pengecam : = [len]jenis{}
  • pengecam := [len]jenis{nilai1, nilai2, …, nilaiN}
  • pengecam := [...]jenis{nilai1, nilai2, …, nilaiN }

Contoh:

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)

Keputusan:

[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]]

Mari lihat iarray1 tatasusunan, yang hanya diisytiharkan dan tidak diberikan nilai Go bantuan bahasa Kami secara automatik menetapkan nilai 0. Melihat iarray2 dan iarray3 sekali lagi, kita dapat melihat bahawa pengisytiharan bahasa Go boleh menunjukkan jenis atau tidak var iarray3 = [5]int32{1, 2, 3, 4, 5} juga betul-betul baik.

2. Kapasiti dan panjang tatasusunan

Kapasiti dan panjang tatasusunan adalah sama. Fungsi cap() dan fungsi len() mengeluarkan kapasiti (iaitu panjang) tatasusunan

3 Jenis

Tatasusunan ialah jenis nilai apabila menetapkan satu tatasusunan kepada tatasusunan lain , yang diluluskan Ia adalah salinan. Walaupun hirisan ialah jenis rujukan, tatasusunan yang dibalut oleh hirisan dipanggil tatasusunan asas bagi hirisan. Lihat contoh berikut:

//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. Menghiris

Dalam bahasa Go, hirisan ialah jujukan unsur yang sama dengan panjang berubah dan kapasiti tetap. Intipati slice dalam bahasa Go ialah tatasusunan. Kapasiti ditetapkan kerana panjang tatasusunan ditetapkan, dan kapasiti kepingan ialah panjang tatasusunan tersembunyi. Panjang pembolehubah merujuk kepada pembolehubah dalam julat panjang tatasusunan.

1. Empat cara untuk mencipta kepingan

  • var slice1 = make([]int,5,10)
  • var slice2 = make([]int,5)
  • var slice3 = []int{}
  • var slice4 = []int{1,2,3,4,5}

Sejajar dengan itu:

  • slice1 := make([]int,5,10)
  • slice2 := make([]int,5)
  • slice3 := []int{}
  • slice4 := []int{1,2,3,4,5}

Output yang sepadan di atas

[0 0 0 0 0]
[0 0 0 0 0]
[]
[1 2 3 4 5]

Seperti yang dapat dilihat dari 3) dan 4), satu-satunya perbezaan antara mencipta kepingan dan mencipta tatasusunan ialah sama ada terdapat nombor dalam "[]" sebelum Taip kepingan, jika tidak, ia mewakili tatasusunan. Kerana kepingan mempunyai panjang berubah

2 Tatasusunan Tersembunyi

Kepingan Go ialah jenis data abstrak di atas tatasusunan, jadi kepingan yang dicipta sentiasa mempunyai Tatasusunan wujud.

Contoh:

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]

Ia juga menunjukkan bahawa kepingan slice0, slice1 dan slice2 adalah rujukan kepada tatasusunan asas yang sama, jadi slice2 telah berubah , dua yang lain akan menjadi

3 tambahkan tambah hirisan

Tambah fungsi terbina dalam boleh menambahkan satu atau lebih nilai lain daripada jenis yang sama pada a. hirisan. Jika bilangan elemen yang dilampirkan melebihi kapasiti kepingan asal, apa yang akhirnya dikembalikan ialah kepingan baharu dalam tatasusunan serba baharu. Jika ia tidak melebihi, maka apa yang akhirnya dikembalikan ialah kepingan baharu dalam tatasusunan asal. Walau apa pun, tambahkan tidak mempunyai kesan pada kepingan asal.

Contoh:

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

Lihat contoh lain:

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])
}

Output di atas:

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 Perbezaan antara tatasusunan dan kepingan dalam GO

Berikut terutamanya melihat beberapa contoh praktikal untuk menggambarkan perbezaan antara tatasusunan dan kepingan.

1. Bentuk tugasan tatasusunan dan kepingan

Contoh 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

Seperti yang dapat dilihat daripada contoh ini, Penugasan tatasusunan ialah salinan nilai, yang merupakan tatasusunan serba baharu. Tugasan kepingan adalah rujukan . Mari lihat contoh lain.

Contoh 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]

Contoh ini sekali lagi menggambarkan: tatasusunan ialah tugasan dan salinan, manakala kepingan hanya rujukan. Pengisytiharan kepingan dalam Contoh 1 dan 2 menggunakan tatasusunan tersembunyi. Mari lihat Contoh 3 sekali lagi, menggunakan tatasusunan tidak tersembunyi.

Contoh 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

Untuk merumuskan tiga contoh di atas, dapat dilihat bahawa hirisan adalah rujukan kepada tatasusunan, termasuk rujukan kepada tatasusunan tersembunyi dan tatasusunan tidak tersembunyi .

2. Tatasusunan digunakan sebagai parameter dan dipanggil oleh fungsi

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)属性

【相关推荐:Go视频教程编程教学

Atas ialah kandungan terperinci Apakah perbezaan antara tatasusunan dan kepingan dalam bahasa go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn