数组
数组中包含的每个数据被称为数组元素(element),一个数组包含的元素个数被称为数组的长度。
[32]byte // 长度为32的数组,每个元素为一个字节
[2*N] struct { x, y int32 } // 复杂类型数组
[1000]*float64 // 指针数组
[3][5]int // 二维数组
[2][2][2]float64 // 等同于[2]([2]([2]float64))
元素访问
for i := 0; i < len(array); i++ {
fmt.Println("Element", i, "of array is", array[i])
}
for i, v := range array {
fmt.Println("Array element[", i, "]=", v)
}
在Go语言中数组是一个值类型(value type)
package main
import "fmt"
func modify(array [10]int) {
array[0] = 10 // 试图修改数组的第一个元素
fmt.Println("In modify(), array values:", array)
}
func main() {
array := [10]int{1,2,3,4,5} // 定义并初始化一个数组,未定义的元素为零值,即0
modify(array) // 传递给一个函数,并试图在函数体内修改这个数组内容
fmt.Println("In main(), array values:", array)
}
该程序的执行结果为:
In modify(), array values: [10 2 3 4 5 0 0 0 0 0]
In main(), array values: [1 2 3 4 5 0 0 0 0 0]
可以用指针的概念解决这个问题
package main
import "fmt"
func modify(array *[10]int) {//接收指针值
array[0] = 10 // 试图修改数组的第一个元素
fmt.Println("In modify(), array values:", array)
}
func main() {
array := [10]int{1,2,3,4,5} // 定义并初始化一个数组,未定义的元素为零值,即0
modify(&array) // 传递指针
fmt.Println("In main(), array values:", array)
}
该程序的执行结果为:
In modify(), array values: &[10 2 3 4 5 0 0 0 0 0]
In main(), array values: [10 2 3 4 5 0 0 0 0 0]
如果你使用多维数组,有一些内容你必须录入:
a := [2][2]int{ [2]int{1,2}, [2]int{3,4} }
a := [2][2]int{ [...]int{1,2}, [...]int{3,4} }//Go 会自动统计元素的个数。
a := [2][2]int{ {1,2}, {3,4} }
切片slice
slice 与array 接近,但是在新的元素加入的时候可以增加长度。slice 总是指向底层的一个array。slice 是一个指向array 的指针,这是其与array 不同的地方;slice 是引用类型,这意味着当赋值某个slice 到另外一个变量,两个引用会指向同一个array。例如,如果一个函数需要一个slice 参数,在其内对slice 元素的修改也会体现在函数调用者中,这和传递底层的array 指针类似。
创建数组切片
创建数组切片的方法主要有两种——基于数组和直接创建。
基于数组:
func main() {
// 先定义一个数组
var myArray [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// 基于数组创建一个数组切片
var mySlice []int = myArray[:5]
fmt.Println("Elements of myArray: ")
for _, v := range myArray {
fmt.Print(v, " ")
}
fmt.Println("\nElements of mySlice: ")
for _, v := range mySlice {
fmt.Print(v, " ")
}
fmt.Println()
}
运行结果为:
Elements of myArray:
1 2 3 4 5 6 7 8 9 10
Elements of mySlice:
1 2 3 4 5
Go语言支持用myArray[first:last]这样的方式来基于数组生成一个数组切片
基于myArray的所有元素创建数组切片:
mySlice = myArray[:]
基于myArray的前5个元素创建数组切片:
mySlice = myArray[:5]
基于从第5个元素开始的所有元素创建数组切片:
mySlice = myArray[5:]
直接创建:
并非一定要事先准备一个数组才能创建数组切片。Go语言提供的内置函数make()可以用于灵活地创建数组切片。当然,事实上还会有一个匿名数组被创建出来,只是不需要我们来操心而已。
创建一个初始元素个数为5的数组切片,元素初始值为0:
mySlice1 := make([]int, 5)
创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间:
mySlice2 := make([]int, 5, 10)
直接创建并初始化包含5个元素的数组切片:
mySlice3 := []int{1, 2, 3, 4, 5}
直接创建并初始化包含4个元素的数组切片:
mySlice3 := []interface{}{3,"str", []int{3,4},func() {fmt.Println()}}
len() 和 cap()函数
因为切片(Slice)是数组上的抽象。它实际上使用数组作为底层结构体.len()函数返回切片中存在的元素数量,其中cap()函数返回切片(Slice)的容量(大小),即可容纳多少个元素。以下是解释切片(Slice)的用法的示例:
package main
import "fmt"
func main() {
var numbers = make([]int,3,5)
printSlice(numbers)
}
func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}
当上述代码编译和执行时,它产生以下结果:
len=3 cap=5 slice=[0 0 0]
append()和copy()函数
切片(Slice)允许使用append()函数增加切片的容量(大小)。使用copy()函数,将源切片的内容复制到目标切片。以下是示例:
package main
import "fmt"
func main() {
var numbers []int
printSlice(numbers)
/* append allows nil slice */
numbers = append(numbers, 0)
printSlice(numbers)
/* add one element to slice*/
numbers = append(numbers, 1)
printSlice(numbers)
/* add more than one element at a time*/
numbers = append(numbers, 2,3,4)
printSlice(numbers)
/* create a slice numbers1 with double the capacity of earlier slice*/
numbers1 := make([]int, len(numbers), (cap(numbers))*2)
/* copy content of numbers to numbers1 */
copy(numbers1,numbers)
printSlice(numbers1)
}
func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}
Go
当上述代码编译和执行时,它产生以下结果:
len=0 cap=0 slice=[]
len=1 cap=2 slice=[0]
len=2 cap=2 slice=[0 1]
len=5 cap=8 slice=[0 1 2 3 4]
len=5 cap=16 slice=[0 1 2 3 4]
字典map
map 可以认为是一个用字符串做索引的数组(在其最简单的形式下)。下面定义了map 类型,用于将string(月的缩写)转换为int – 那个月的天数。一般定义map 的方法是:map[<from type>]<to type>
monthdays := map[string]int{
"Jan": 31, "Feb": 28, "Mar": 31,
"Apr": 30, "May": 31, "Jun": 30,
"Jul": 31, "Aug": 31, "Sep": 30,
"Oct": 31, "Nov": 30, "Dec": 31, //逗号是必须的
}
留意,当只需要声明一个map 的时候,使用make 的形式:
monthdays := make(map[string]int)
当在map 中索引(搜索)时,使用方括号。例如打印出12 月的天数:
fmt.Printf("%d\n",monthdays["Dec"])
当对array、slice、string 或者map 循环遍历的时候,range 会帮助你,每次调用,它都会返回一个键和对应的值。
year := 0
for _, days := range monthdays { 键没有使用,因此用_, days
year += days
}
fmt.Printf("Numbers of days in a year:%d\n", year)
向map 增加元素,可以这样做:
monthdays["Undecim"] = 30 //添加一个月
monthdays["Feb"] = 29 //年时重写这个元素
检查元素是否存在,可以使用下面的方式:
var value int
var present bool
value, present =monthdays["Jan"] //如果存在,present 则有值true
或者更接近Go 的方式
v, ok := monthdays["Jan"] //“逗号ok”形式
也可以从map 中移除元素:
delete(monthdays, "Mar") //删除"Mar"
通常来说语句delete(m, x) 会删除map 中由m[x] 建立的实例。