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

·  阅读 534

## 数组

##### 数组的声明

``````package main

import (
"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 main

import (
"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 main

import (
"fmt"
)

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

Run in playground

``````package main

import (
"fmt"
)

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

Run in playground

``````package main

func 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 main

import "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 main

import "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 main

import "fmt"

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

}

Run in playground

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

``````package main

import "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 main

import "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.00

sum of all elements of a 256.5

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

##### 多维数组

``````package main

import (
"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[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
AT&T T-Mobile

## 切片

##### 创建切片

``````package main

import (
"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 main

import (
"fmt"
)

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

Run in playground

##### 修改切片

``````package main

import (
"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 main

import (
"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 main

import (
"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。`fruiteslice``fruitarray`的索引 1 开始创建。因此，`fruiteslice`的容量是从索引 1 开始的`fruitarray`中的元素，即从`orange`开始，该值为 6。因此，`fruiteslice`的容量为 6。该程序输出`length of slice 2 capacity 6.`

``````package main

import (
"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 main

import (
"fmt"
)

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

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

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

``````package main

import (
"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 main

import (
"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 main

import (
"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 main

import (
"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 main

import (
"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 main

import (
"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