1010
1111数组是类型相同的元素的集合。例如,整数 5, 8, 9, 79, 76 的集合就构成了一个数组。Go不允许在数组中混合使用不同类型的元素(比如整数和字符串)。
1212
13- ## 申明
13+ ## 声明
1414
1515数组的类型为` [n]T ` ,其中 ` n ` 表示数组中元素的个数,` T ` 表示数组中元素的类型。元素的个数 ` n ` 也是数组类型的一部分(我们将在稍后详细讨论)。
1616
@@ -51,9 +51,9 @@ func main() {
5151
5252` a[0] ` 表示数组中的第一个元素。程序的输出为:` [12 78 50] ` 。
5353
54- (译者注:可以用下标运算符(` [] ` )来访问数组中的元素,下标从 0 开始,例如 ` a[0] ` 表示数组 a 的第一个元素,` a[1] ` 表示数组 a 的第二元素 ,以此类推。)
54+ (译者注:可以用下标运算符(` [] ` )来访问数组中的元素,下标从 0 开始,例如 ` a[0] ` 表示数组 a 的第一个元素,` a[1] ` 表示数组 a 的第二个元素 ,以此类推。)
5555
56- 可以利用** 速记声明(shorthand declaration)** 的方式来创建同样的数组:
56+ 可以利用** 速记声明(shorthand declaration)** 的方式来创建同样的数组:
5757
5858``` golang
5959package main
@@ -87,7 +87,7 @@ func main() {
8787}
8888```
8989
90- 上面程序的第 8 行:` a := [3]int{12} ` 声明了一个长度为 3 的数组,但是只提供了一个初值 12。剩下的两个元素被自动赋值为 0。程序 的输出为:` [12 0 0] ` 。
90+ 上面程序的第 8 行:` a := [3]int{12} ` 声明了一个长度为 3 的数组,但是只提供了一个初值 12。剩下的两个元素被自动赋值为 0。程序 的输出为:` [12 0 0] ` 。
9191
9292在声明数组时你可以忽略数组的长度并用` ... ` 代替,让编译器为你自动推导数组的长度。比如下面的程序:
9393
@@ -104,7 +104,7 @@ func main() {
104104}
105105```
106106
107- 上面已经提到,数组的长度是数组类型的一部分。因此 ` [5]int ` 和 ` [25]int ` 是两个不同类型的数组。正是因为如此,一个数组不能动态改变长度。不要担心这个限制,因为切片(` slices ` )可以弥补这个不足。
107+ 上面已经提到,数组的长度是数组类型的一部分。因此 ` [5]int ` 和 ` [25]int ` 是两个不同类型的数组。正是因为如此,一个数组不能动态改变长度。不要担心这个限制,因为切片(` slices ` )可以弥补这个不足。
108108
109109``` golang
110110package main
@@ -116,7 +116,7 @@ func main() {
116116}
117117```
118118
119- 在上面程序的第 6 行,我们试图将一个` [3]int ` 类型的数组赋值给一个 ` [5]int ` 类型的数组,这是不允许的。编译会报错:` main.go:6: cannot use a (type [3]int) as type [5]int in assignment。 `
119+ 在上面程序的第 6 行,我们试图将一个` [3]int ` 类型的数组赋值给一个 ` [5]int ` 类型的数组,这是不允许的。编译会报错:` main.go:6: cannot use a (type [3]int) as type [5]int in assignment。 `
120120
121121## 数组是值类型
122122
@@ -189,7 +189,7 @@ func main() {
189189
190190## 使用 range 遍历数组
191191
192- ` for ` 循环可以用来遍历数组中的元素:
192+ ` for ` 循环可以用来遍历数组中的元素:
193193
194194``` golang
195195package main
@@ -212,7 +212,7 @@ func main() {
2122123 th element of a is 78.00
213213```
214214
215- Go 提供了一个更简单,更简洁的遍历数组的方法:使用 ` range for ` 。 range 返回数组的索引和索引对应的值。让我们用 range for 重写上面的程序(除此之外我们还计算了数组元素的总和)。
215+ Go 提供了一个更简单,更简洁的遍历数组的方法:使用 range 形式的 for 循环。 ` range ` 返回数组的索引和索引对应的值。让我们用 range for 重写上面的程序(除此之外我们还计算了数组元素的总和)。
216216``` golang
217217package main
218218
@@ -247,7 +247,7 @@ for _, v := range a { //ignores index
247247}
248248```
249249
250- 上面的代码忽略了索引。同样的 ,也可以忽略值。
250+ 上面的代码忽略了索引。用类似的方法 ,也可以忽略值。
251251
252252## 多维数组
253253
@@ -288,7 +288,7 @@ func main() {
288288}
289289```
290290
291- 上面的程序中,第 17 行利用速记声明创建了一个二维数组 a。第 20 行的逗号是必须的,这是因为词法分析器会根据一些简单的规则自动插入分号 。如果你想了解更多,请阅读:https://golang.org/doc/effective_go.html#semicolons 。
291+ 上面的程序中,第 17 行利用速记声明创建了一个二维数组 a。第 20 行的逗号是必须的,因为词法分析器会根据一些简单的规则自动插入分号 。如果你想了解更多,请阅读:https://golang.org/doc/effective_go.html#semicolons 。
292292
293293在第 23 行声明了另一个二维数组 b,并通过索引的方式给数组 b 中的每一个元素赋值。这是初始化二维数组的另一种方式。
294294
@@ -312,7 +312,7 @@ AT&T T-Mobile
312312
313313## 创建切片
314314
315- 元素类型为 ` T ` 的切片表示为: ` []T ` 。
315+ 元素类型为 ` T ` 的切片表示为: ` []T ` 。
316316
317317``` golang
318318package main
@@ -328,7 +328,7 @@ func main() {
328328}
329329```
330330
331- 通过 ` a[start:end] ` 这样的语法创建了一个从` a[start] ` 到 ` a[end -1] ` 的切片。在上面的程序中,第 9 行` a[1:4] ` 创建了一个从 ` a[1] ` 到 ` a[3] ` 的切片。因此 b 的值为:` [77 78 79] ` 。
331+ 通过 ` a[start:end] ` 这样的语法创建了一个从` a[start] ` 到 ` a[end -1] ` 的切片。在上面的程序中,第 9 行` a[1:4] ` 创建了一个从 ` a[1] ` 到 ` a[3] ` 的切片。因此 b 的值为:` [77 78 79] ` 。
332332
333333下面是创建切片的另一种方式:
334334
@@ -345,7 +345,7 @@ func main() {
345345}
346346```
347347
348- 在上面的程序中,第 9 行 ` c := []int{6, 7, 8} ` 创建了一个长度为 3 的 int 数组,并返回一个切片给 c。
348+ 在上面的程序中,第 9 行 ` c := []int{6, 7, 8} ` 创建了一个长度为 3 的 int 数组,并返回一个切片给 c。
349349
350350## 修改切片
351351
@@ -397,7 +397,7 @@ func main() {
397397}
398398```
399399
400- 可以看到,在第 9 行,` numa[:] ` 中缺少了开始和结束的索引值,这种情况下开始和结束的索引值默认为 ` 0 ` 和` len(numa) ` 。这里 ` nums1 ` 和 ` nums2 ` 共享了同一个数组。程序的输出为:
400+ 可以看到,在第 9 行,` numa[:] ` 中缺少了开始和结束的索引值,这种情况下开始和结束的索引值默认为 ` 0 ` 和` len(numa) ` 。这里 ` nums1 ` 和 ` nums2 ` 共享了同一个数组。程序的输出为:
401401
402402``` golang
403403array before change 1 [78 79 80 ]
@@ -429,11 +429,11 @@ func main() {
429429}
430430```
431431
432- 在上面的程序中,创建了一个以 fruitarray 为底层数组,索引从 1 到 3 的切片 ` fruitslice ` 。 因此 fruitslice 长度为 2。
432+ 在上面的程序中,创建了一个以 ` fruitarray ` 为底层数组,索引从 1 到 2 的切片 ` fruitslice ` , 因此 fruitslice 长度为 2。
433433
434- ` fruitarray ` 的长度是 7。` fruiteslice ` 是从 ` fruitarray ` 的索引 1 开始的。因此 ` fruiteslice ` 的容量是从 ` fruitarray ` 的第 1 个元素开始算起的数组中的元素个数,这个值是 6。因此 ` fruitslice ` 的容量是 6。程序的输出为:` length of slice 2 capacity 6 `
434+ ` fruitarray ` 的长度是 7。` fruiteslice ` 是从 ` fruitarray ` 的索引 1 开始的。因此 ` fruiteslice ` 的容量是从 ` fruitarray ` 的第 1 个元素开始算起的数组中的元素个数,这个值是 6。因此 ` fruitslice ` 的容量是 6。程序的输出为:` length of slice 2 capacity 6 `
435435
436- 切片的长度可以动态的改变(最大为其容量)。任何超出最大容量的操作都会发生运行时错误 。
436+ 切片的长度可以动态地改变(最大长度为其容量)。任何超出切片容量的操作都会发生运行错误 。
437437
438438``` golang
439439package main
@@ -460,7 +460,7 @@ After re-slicing length is 6 and capacity is 6
460460
461461## 用 make 创建切片
462462
463- 内置函数` func make([]T, len, cap) []T ` 可以用来创建切片,该函数接受** 长度** 和** 容量** 作为参数,返回切片。容量是可选的,默认与长度相同。使用 make 函数将会创建一个数组并返回它的切片。
463+ 内置函数` func make([]T, len, cap) []T ` 可以用来创建切片,该函数接受** 长度** 和** 容量** 作为参数,返回切片。容量是可选的,默认与长度相同。使用 make 函数将会创建一个数组并返回它的切片。
464464
465465``` golang
466466package main
@@ -483,7 +483,7 @@ func main() {
483483
484484` x ...T ` 表示 append 函数可以接受的参数个数是可变的。这种函数叫做变参函数。
485485
486- 你可能会问一个问题:如果切片是建立在数组之上的,而数组本身不能改变长度,那么切片是如何动态改变长度的呢?实际发生的情况是,当新元素通过调用 append 函数追加到切片末尾时,如果超出了容量,append 内部会创建一个新的数组。并将原有数组的元素被拷贝给这个新的数组 ,最后返回建立在这个新数组上的切片。这个新切片的容量是旧切片的二倍(译者注:当超出切片的容量时,append 将会在其内部创建新的数组,该数组的大小是原切片容量的 2 倍。最后 append 返回这个数组的全切片,即从 0 到 length - 1 的切片)。下面的程序使事情变得明朗 :
486+ 你可能会问一个问题:如果切片是建立在数组之上的,而数组本身不能改变长度,那么切片是如何动态改变长度的呢?实际发生的情况是,当新元素通过调用 append 函数追加到切片末尾时,如果超出了容量,append 内部会创建一个新的数组。并将原有数组的元素拷贝给这个新的数组 ,最后返回建立在这个新数组上的切片。这个新切片的容量是旧切片的二倍(译者注:当超出切片的容量时,append 将会在其内部创建新的数组,该数组的大小是原切片容量的 2 倍。最后 append 返回这个数组的全切片,即从 0 到 length - 1 的切片)。下面的程序会帮助你理解这一知识点 :
487487
488488``` golang
489489package main
@@ -500,7 +500,7 @@ func main() {
500500}
501501```
502502
503- 在上面的程序中,cars 的容量开始时为 3。在第 10 行我们追加了一个新的元素给 ` cars ` ,并将 ` append(cars, "Toyota") ` 的返回值重新复制给 cars。现在 cars 的容量翻倍,变为 6。上面的程序输出为:
503+ 在上面的程序中,cars 的容量开始时为 3。在第 10 行我们追加了一个新的元素给 ` cars ` ,并将 ` append(cars, "Toyota") ` 的返回值重新复制给 cars。现在 cars 的容量翻倍,变为 6。上面的程序输出为:
504504
505505``` golang
506506cars: [Ferrari Honda Ford ] has old length 3 and capacity 3
@@ -588,7 +588,7 @@ func main() {
588588}
589589```
590590
591- 在上面的程序中,第 17 行将切片中的每个元素的值减2 。在函数调用之后打印切片的的内容,发现切片内容发生了改变。你可以回想一下,这不同于一个数组,对函数内部的数组所做的更改在函数外不可见。上面的程序输出如下:
591+ 在上面的程序中,第 17 行将切片中的每个元素的值减 2 。在函数调用之后打印切片的的内容,发现切片内容发生了改变。你可以回想一下,这不同于一个数组,对函数内部的数组所做的更改在函数外不可见。上面的程序输出如下:
592592
593593``` golang
594594array before function call [8 7 6 ]
@@ -634,7 +634,7 @@ Go Rust
634634
635635切片保留对底层数组的引用。只要切片存在于内存中,数组就不能被垃圾回收。这在内存管理方便可能是值得关注的。假设我们有一个非常大的数组,而我们只需要处理它的一小部分,为此我们创建这个数组的一个切片,并处理这个切片。这里要注意的事情是,数组仍然存在于内存中,因为切片正在引用它。
636636
637- 解决该问题的一个方法是使用 copy 函数 ` func copy(dst, src []T) int ` 来创建该切片的一个拷贝。这样我们就可以使用这个新的切片,原来的数组可以被垃圾回收。
637+ 解决该问题的一个方法是使用 copy 函数 ` func copy(dst, src []T) int ` 来创建该切片的一个拷贝。这样我们就可以使用这个新的切片,原来的数组可以被垃圾回收。
638638
639639``` golang
640640package main
@@ -656,7 +656,7 @@ func main() {
656656}
657657```
658658
659- 在上面程序中,第 9 行 ` neededCountries := countries[:len(countries)-2] ` 创建一个底层数组为 ` countries ` 并排除最后两个元素的切片。第 11 行将 ` neededCountries ` 拷贝到 ` countriesCpy ` 并在下一行返回 ` countriesCpy ` 。现在数组 ` countries ` 可以被垃圾回收,因为 ` neededCountries ` 不再被引用。
659+ 在上面程序中,第 9 行 ` neededCountries := countries[:len(countries)-2] ` 创建一个底层数组为 ` countries ` 并排除最后两个元素的切片。第 11 行将 ` neededCountries ` 拷贝到 ` countriesCpy ` 并在下一行返回 ` countriesCpy ` 。现在数组 ` countries ` 可以被垃圾回收,因为 ` neededCountries ` 不再被引用。
660660
661661我(原文作者)已经将我们讨论的所有概念汇总到一个程序中,你可以从 [ github] ( https://github.com/golangbot/arraysandslices ) 下载。
662662
@@ -666,9 +666,9 @@ func main() {
666666[ 深入解析 Go 中 Slice 底层实现] ( https://halfrost.com/go_slice/ )
667667###### 创建(定义)数组
668668数组在Go中是值类型,而不是引用(其他语言的数组则是引用类型)
669- PS:切片(slice)是一个引用类型
670- 数组不是统一的类型,大小不同的数组是不可以比较的
671- 不同数组类型是不可以比较的
669+ 670+ PS:切片(slice)是一个引用类型。 数组不是统一的类型,大小不同的数组是不可以比较的,不同数组类型是不可以比较的
671+ 672672``` golang
673673var a [2 ]int
674674var b [3 ]string
@@ -689,9 +689,9 @@ var d = [...]int{19:90} // 尽可能的满足索引值得数组
689689a := [...]int {19 :100 }
690690
691691// 指向数组的指针
692- var p *[20 ]int = &a // 长度为20的int型数组,这里的数组长度`20`必须和a数组长度相等
692+ var p *[20 ]int = &a // 长度为20的int型数组,这里的数组长度`20`必须和a数组长度相等
693693fmt.Println (p) // 以上表示取这样一个数组的地址
694- // 打印结果:&[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 19 ]
694+ // 打印结果:&[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 100 ]
695695
696696// 指向指针的数组
697697x , y := 1 , 2
@@ -702,7 +702,7 @@ fmt.Println("pp is ",pp) // 打印结果:pp is [0xc420012128 0xc420012130]
702702
703703``` golang
704704 ppp := new ([10 ]int )
705- fmt.Println (" ----ppp-------" ,ppp); // 输出结果:`&[0 0 0 0 0 0 0 0 0 0]`
705+ fmt.Println (" ----ppp-------" ,ppp); // 输出结果:`----ppp------- &[0 0 0 0 0 0 0 0 0 0]`
706706// 以上为指向数组的指针
707707```
708708
@@ -712,12 +712,12 @@ fmt.Println("----ppp-------",ppp); //输出结果:`&[0 0 0 0 0 0 0 0 0 0]`
712712// 第一种方式
713713n := [10 ]int {}
714714n[1 ] = 10
715- fmt.Println (" -----1------" ,n) // 输出:`[0 10 0 0 0 0 0 0 0 0]`
715+ fmt.Println (" -----1------" ,n) // 输出:`-----1------ [0 10 0 0 0 0 0 0 0 0]`
716716
717717// 第二种方式
718718m := new ([10 ]int )
719719m[1 ] = 20
720- fmt.Println (" -----2------" ,m) // 输出:`&[0 20 0 0 0 0 0 0 0 0]`
720+ fmt.Println (" -----2------" ,m) // 输出:`-----2------ &[0 20 0 0 0 0 0 0 0 0]`
721721```
722722
723723###### 多维数组
@@ -804,7 +804,7 @@ func main() {
804804 s7 := []byte {' a' ,' b' ,' c' ,' d' ,' e' ,' f' ,' g' ,' h' ,' i' ,' j' ,' k' } // 切片底层对应的数组
805805
806806 slice_a := s7[2 :5 ]
807- fmt.Println (slice_a) // 输出的assica码 值 [99 100 101]
807+ fmt.Println (slice_a) // 输出的ascii码 值 [99 100 101]
808808 fmt.Println (string (slice_a)) // 格式化为字符串输出
809809 fmt.Println (len (slice_a),cap (slice_a))
810810
@@ -817,7 +817,7 @@ func main() {
817817 s8 = append (s8, 12 , 48 )
818818 fmt.Printf (" %v %p " , s8, s8) // 格式化打印值和内存地址:[0 0 0 12 48] 0xc042074030
819819
820- // 追加的元素如果没有超多切片容量 ,则切片的地址是不变的,否则内存地址会变
820+ // 追加的元素如果没有超过切片容量 ,则切片的地址是不变的,否则内存地址会变
821821 s8 = append (s8, 66 , 88 )
822822 fmt.Printf (" %v %p \n " , s8, s8) // [0 0 0 12 48 66 88] 0xc042048060
823823
@@ -828,7 +828,7 @@ func main() {
828828 fmt.Println (s9) // [33 44 55 4 5 6 7]
829829
830830 copy (s10,s9)
831- fmt.Println (s10) // [33 44 55 ]
831+ fmt.Println (s10) // [1 2 3 ]
832832
833833 copy (s9[2 :4 ],s10[0 :2 ])
834834 fmt.Println (s9) // [1 2 33 44 5 6 7]
0 commit comments