# [译] part 11: goalng 数组和切片

https://juejin.im/post/5cb6084b51882529e56277f9

## 数组

##### 数组的声明

package mainimport (      "fmt")func main() {      var a [3]int //int array with length 3    fmt.Println(a)}

Run in playground var a [3]int 声明了一个长度为 3 的整型数组，该数组所有的元素会被自动初始化为数组类型的零值。在这个例子中数组的类型为整数，所以 a 数组所有的元素会被初始化为 0。运行代码会输出，[0 0 0]

package mainimport (      "fmt")func main() {      var a [3]int //int array with length 3    a[0] = 12 // array index starts at 0    a[1] = 78    a[2] = 50    fmt.Println(a)}

Run in playground

package main import (      "fmt")func main() {      a := [3]int{12, 78, 50} // short hand declaration to create array    fmt.Println(a)}

Run in playground

package mainimport (      "fmt")func main() {      a := [3]int{12}     fmt.Println(a)}

Run in playground

package mainimport (      "fmt")func main() {      a := [...]int{12, 78, 50} // ... makes the compiler determine the length    fmt.Println(a)}

Run in playground

package mainfunc main() {      a := [3]int{5, 78, 8}    var b [5]int    b = a //not possible since [3]int and [5]int are distinct types}

Run in playground

##### 数组是值传递类型

Go 中的数组是值传递类型而不是引用传递类型。这意味着当它们赋值给新变量时，会将原始数组的副本赋给新变量。如果对新变量进行了更改，则它不会改变原来的数组。

package mainimport "fmt"func main() {      a := [...]string{"USA", "China", "India", "Germany", "France"}    b := a // a copy of a is assigned to b    b[0] = "Singapore"    fmt.Println("a is ", a)    fmt.Println("b is ", b) }

Run in playground

a is [USA China India Germany France]  b is [Singapore China India Germany France]

package mainimport "fmt"func changeLocal(num [5]int) {      num[0] = 55    fmt.Println("inside function ", num)}func main() {      num := [...]int{5, 6, 7, 8, 8}    fmt.Println("before passing to function ", num)    changeLocal(num) //num is passed by value    fmt.Println("after passing to function ", num)}

Run in playground

before passing to function  [5 6 7 8 8]  inside function  [55 6 7 8 8]  after passing to function  [5 6 7 8 8]
##### 数组的长度

package mainimport "fmt"func main() {      a := [...]float64{67.7, 89.8, 21, 78}    fmt.Println("length of a is",len(a))}

Run in playground

##### 使用 range 迭代数组

package mainimport "fmt"func main() {      a := [...]float64{67.7, 89.8, 21, 78}    for i := 0; i < len(a); i++ { //looping from 0 to the length of the array        fmt.Printf("%d th element of a is %.2f\n", i, a[i])    }}

Run in playground 上述代码使用了for循环迭代了数组的所有元素，该程序将输出，

0 th element of a is 67.70  1 th element of a is 89.80  2 th element of a is 21.00  3 th element of a is 78.00

Go 提供了一种更好，更简洁的方法，通过使用for循环的range形式迭代数组。 range返回索引和该索引处的值。让我们使用range重写上面的代码，并计算所有元素的和。

package mainimport "fmt"func main() {      a := [...]float64{67.7, 89.8, 21, 78}    sum := float64(0)    for i, v := range a {//range returns both the index and value        fmt.Printf("%d the element of a is %.2f\n", i, v)        sum += v    }    fmt.Println("\nsum of all elements of a",sum)}

Run in playground

0 the element of a is 67.70  1 the element of a is 89.80  2 the element of a is 21.00  3 the element of a is 78.00sum of all elements of a 256.5

for _, v := range a { //ignores index  }

##### 多维数组

package mainimport (      "fmt")func printarray(a [3][2]string) {      for _, v1 := range a {        for _, v2 := range v1 {            fmt.Printf("%s ", v2)        }        fmt.Printf("\n")    }}func main() {      a := [3][2]string{        {"lion", "tiger"},        {"cat", "dog"},        {"pigeon", "peacock"}, //this comma is necessary. The compiler will complain if you omit this comma    }    printarray(a)    var b [3][2]string    b[0][0] = "apple"    b[0][1] = "samsung"    b[1][0] = "microsoft"    b[1][1] = "google"    b[2][0] = "AT&T"    b[2][1] = "T-Mobile"    fmt.Printf("\n")    printarray(b)}

Run in playground

lion tiger  cat dog  pigeon peacock apple samsung  microsoft google  AT&T T-Mobile

## 切片

##### 创建切片

package mainimport (      "fmt")func main() {      a := [5]int{76, 77, 78, 79, 80}    var b []int = a[1:4] //creates a slice from a[1] to a[3]    fmt.Println(b)}

Run in playground

package mainimport (      "fmt")func main() {      c := []int{6, 7, 8} //creates and array and returns a slice reference    fmt.Println(c)}

Run in playground

##### 修改切片

package mainimport (      "fmt")func main() {      darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59}    dslice := darr[2:5]    fmt.Println("array before",darr)    for i := range dslice {        dslice[i]++    }    fmt.Println("array after",darr) }

Run in playground

array before [57 89 90 82 100 78 67 69 59]  array after [57 89 91 83 101 78 67 69 59]

package mainimport (      "fmt")func main() {      numa := [3]int{78, 79 ,80}    nums1 := numa[:] //creates a slice which contains all elements of the array    nums2 := numa[:]    fmt.Println("array before change 1",numa)    nums1[0] = 100    fmt.Println("array after modification to slice nums1", numa)    nums2[1] = 101    fmt.Println("array after modification to slice nums2", numa)}

Run in playground

array before change 1 [78 79 80]  array after modification to slice nums1 [100 79 80]  array after modification to slice nums2 [100 101 80]

## 切片的长度和容量

package mainimport (      "fmt")func main() {      fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon", "pine apple", "chikoo"}    fruitslice := fruitarray[1:3]    fmt.Printf("length of slice %d capacity %d", len(fruitslice), cap(fruitslice)) //length of is 2 and capacity is 6}

Run in playground

fruitarray的长度为 7。fruiteslicefruitarray的索引 1 开始创建。因此，fruiteslice的容量是从索引 1 开始的fruitarray中的元素，即从orange开始，该值为 6。因此，fruiteslice的容量为 6。该程序输出length of slice 2 capacity 6.

package mainimport (      "fmt")func main() {      fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon", "pine apple", "chikoo"}    fruitslice := fruitarray[1:3]    fmt.Printf("length of slice %d capacity %d\n", len(fruitslice), cap(fruitslice)) //length of is 2 and capacity is 6    fruitslice = fruitslice[:cap(fruitslice)] //re-slicing furitslice till its capacity    fmt.Println("After re-slicing length is",len(fruitslice), "and capacity is",cap(fruitslice))}

Run in playground

length of slice 2 capacity 6  After re-slicing length is 6 and capacity is 6
##### 使用 make 函数创建切片

func make([]T, len, cap) []T 通过传递类型，长度，容量来创建一个切片。容量参数是可选的，默认值是长度。

make函数创建一个数组并返回一个切片引用。

package mainimport (      "fmt")func main() {      i := make([]int, 5, 5)    fmt.Println(i)}

Run in playground 使用make函数创建的切片默认会被零值填充，上述程序将输出[0 0 0 0 0]

##### 为切片增加元素

package mainimport (      "fmt")func main() {      cars := []string{"Ferrari", "Honda", "Ford"}    fmt.Println("cars:", cars, "has old length", len(cars), "and capacity", cap(cars)) //capacity of cars is 3    cars = append(cars, "Toyota")    fmt.Println("cars:", cars, "has new length", len(cars), "and capacity", cap(cars)) //capacity of cars is doubled to 6}

Run in playground

cars: [Ferrari Honda Ford] has old length 3 and capacity 3  cars: [Ferrari Honda Ford Toyota] has new length 4 and capacity 6

package mainimport (      "fmt")func main() {      var names []string //zero value of a slice is nil    if names == nil {        fmt.Println("slice is nil going to append")        names = append(names, "John", "Sebastian", "Vinay")        fmt.Println("names contents:",names)    }}

Run in playground

names是一个nil切片，我们给names添加了 3 个字符串，该程序输出，

slice is nil going to append  names contents: [John Sebastian Vinay]

package mainimport (      "fmt")func main() {      veggies := []string{"potatoes","tomatoes","brinjal"}    fruits := []string{"oranges","apples"}    food := append(veggies, fruits...)    fmt.Println("food:",food)}

Run in playground

##### 切片作为函数的参数

type slice struct {      Length        int    Capacity      int    ZerothElement *byte}

package mainimport (      "fmt")func subtactOne(numbers []int) {      for i := range numbers {        numbers[i] -= 2    }}func main() {      nos := []int{8, 7, 6}    fmt.Println("slice before function call", nos)    subtactOne(nos)                               //function modifies the slice    fmt.Println("slice after function call", nos) //modifications are visible outside}

Run in playground

slice before function call [8 7 6]  slice after function call [6 5 4]
##### 多维切片

package mainimport (      "fmt")func main() {       pls := [][]string {            {"C", "C++"},            {"JavaScript"},            {"Go", "Rust"},            }    for _, v1 := range pls {        for _, v2 := range v1 {            fmt.Printf("%s ", v2)        }        fmt.Printf("\n")    }}

Run in playground

C C++  JavaScript  Go Rust
##### 内存优化

package mainimport (      "fmt")func countries() []string {      countries := []string{"USA", "Singapore", "Germany", "India", "Australia"}    neededCountries := countries[:len(countries)-2]    countriesCpy := make([]string, len(neededCountries))    copy(countriesCpy, neededCountries) //copies neededCountries to countriesCpy    return countriesCpy}func main() {      countriesNeeded := countries()    fmt.Println(countriesNeeded)}

Run in playground