数组
数组是同一类型元素的集合。例如,整数集合 5,8,9,79,76 形成一个数组。Go 语言中不允许混合不同类型的元素,例如包含字符串和整数的数组。(译者注:当然,如果是 interface{} 类型数组,可以包含任意类型)
注意:数组在定义阶段,长度和类型就固定了,以后不能更改
数组的声明
一个数组的表示形式为[n]T。n表示数组中元素的数量,T代表每个元素的类型。元素n也是该类型的一部分。
例子:最简单的定义
package main import "fmt" func main() { var a[5]int #定义一个长度为5的int类型数组,因为没有赋值int是0 fmt.Println(a) }
#结果
[0 0 0 0 0]
定义并赋初值
package main import "fmt" func main() {
#三种定义赋值的方式,因为只赋值了4个值,所以最后一个为0 var a[5]int=[5]int{1,2,3,4} #第一种 var a=[5]int{1,2,3,4} #第二种 a:=[5]int{1,2,3,4} #第三种 a[2]=100 #索引值为2的数据修改为100 fmt.Println(a) }
#结果都是
[1 2 100 4 0]
定义时给定某位置赋值
例子:给第5个位置设置为99
package main import "fmt" func main() { a:=[10]int{1,2,4:99} #注意:go语言数组不支持负索引a[-2]这样的 fmt.Println(a) }
#结果
[1 2 0 0 99 0 0 0 0 0]
数组是值类型
Go 中的数组是值类型而不是引用类型。这意味着当数组赋值给一个新的变量时,该变量会得到一个原始数组的一个副本。如果对新变量进行更改,则不会影响原始数组。(*******)
所有的函数传参都是copy传递,在python传参不可变类型是值传参,复制值的大小,可变类型是引用传参,复制值的地址传递。
package main import "fmt" func main() { a:=[4]int{1,2,3,4} test6(a) fmt.Println(a) } func test6(b [4]int){ b[0]=100 #b的数据修改不会影响到a fmt.Println(b) }
#结果
[100 2 3 4]
[1 2 3 4]
数组的长度
使用len函数,得到数组的长度
package main import "fmt" func main() { a:=[4]int{1,2,3,4} fmt.Println(len(a)) } #结果 4
数组大小是类型一部分
var a [4]int=[4]int{1,2,} var b [5]int=[5]int{4,5,}
这两个数组类型不一样的,因为考虑到长度大小不一样
与或非(&& || !)
a:=10 if !(a>9||a<6){ }
使用range迭代数组
用for循环遍历数组中的元素
package main import "fmt" func main() { var a =[4]int{1,2,} for i:=0;i<len(a);i++{ fmt.Println(a[i]) } } #结果 1 2 0 0
Go提供了通过使用for循环的range方法来遍历数组。range返回索引和该索引处的值
注意:如果range有两个返回值接收:一个是索引值,一个是值。如果只有一个返回值接收:就只显示索引
package main import "fmt" func main() { var a =[4]int{1,2,} for i,v:=range a { #如果有两个值接收:一个是索引,一个是值。 fmt.Println("------",i) fmt.Println(v) } }
多维数组
package main import "fmt" func main() { var a [7][2]int #生成7个 a[0][1]=100 fmt.Println(a) } #结果 [[0 100] [0 0] [0 0] [0 0] [0 0] [0 0] [0 0]]
切片
切片是由数组建立的一种方便、灵活且功能强大的包装(Wrapper)。切片本身不拥有任何数据。它们只是对现有数组的引用。
创建切片
带有 T 类型元素的切片由 []T
表示
package main import "fmt" func main() { var a=[5]int{1,2,3,4,5} var b[]int=a[2:4] #只是对数组的引用 fmt.Println(b) }
另外一种创建方式:直接定义,赋值
package main import "fmt" func main() { var b[]int #只定义了没有赋初始值 var a=[]int{1,2,3} #定义切片并赋初始值 fmt.Println(a) fmt.Println(b) } #结果 [1 2 3] [] #切片是空值,但是是nil类型,说明切片是引用传递参数
使用make创建一个切片
func make([]T,len,cap)[]T 通过传递类型,长度和容量来创建切片。容量是可选参数, 默认值为切片长度。make 函数创建一个数组,并返回引用该数组的切片。
package main import "fmt" func main() { var a=make([]int,3) fmt.Println(a) }
#结果
[0 0 0]
切片的长度(len)和容量(cap)
package main import "fmt" func main() { var a=[5]int{1,2,3,4,5} var b[]int=a[2:4] fmt.Println(len(b)) //2 fmt.Println(cap(b)) //3 因为容量是从截取的索引位置开始算后面有多少个,所以是3 var c=make([]int,3,4) #make定义一个切片,长度为3,容量为4 fmt.Println(len(c)) //3 fmt.Println(cap(c)) //4 }
切片的修改
切片自己不拥有任何数据。它只是底层数组的一种表示。对切片所做的任何修改都会反映在底层数组中。
底层数组的修改会影响切片,切片的修改也会影响底层数组
package main import "fmt" func main() { var a=[5]int{1,2,3,4,5} var b[]int=a[2:4] a[2]=100 b[1]=20 fmt.Println(a) fmt.Println(b) //本来是[3,4],但是原数组和切片都改了都会互相影响数据值 } #结果 [1 2 100 20 5] [100 20]
切片追加值
正如我们已经知道数组的长度是固定的,它的长度不能增加。 切片是动态的,使用 append
可以将新元素追加到切片上。append 函数的定义是 func append(s[]T,x ... T)[]T
。
x ... T 在函数定义中表示该函数接受参数 x 的个数是可变的。这些类型的函数被称为[可变函数]。
有一个问题可能会困扰你。如果切片由数组支持,并且数组本身的长度是固定的,那么切片如何具有动态长度。以及内部发生了什么,当新的元素被添加到切片时,超过原本的容量,会创建一个新的数组。现有数组的元素被复制到这个新数组中,并返回这个新数组的新切片引用。现在新切片的容量是旧切片的两倍。对创建新的数组进行修改,不会对原本的数组进行改变。
package main import "fmt" func main() { var a=[7]int{1,2,3,4,5,6,7} var b[]int=a[2:6] fmt.Println(len(b)) //4 fmt.Println(cap(b)) //5 b=append(b,555) //第一次追加 b[0]=100 fmt.Println(b) //[100 4 5 6 555] fmt.Println(a) //[1 2 100 4 5 6 555] b=append(b,666) //第二次追加 fmt.Println(len(b)) //6 fmt.Println(cap(b)) //10 b[0]=50 fmt.Println(b) //[50 4 5 6 555 666] fmt.Println(a) //[1 2 100 4 5 6 555] }
注意:变量b在最开始时候容量是5,在第二次追加之后长度为10,之前的容量5已经不够了,所以变成原来容量的两倍。超过了容量之后再追加不会再对原本的a数据进行修改
切片的函数传递(当切片作为参数传递给函数时,函数内所做的更改也会在函数外可见)
package main import "fmt" func main() { var b=make([]int,3,4) #创建一个切片 test(b) fmt.Println(b) } func test(b[]int) { b[0]=999 #函数内修改切片 fmt.Println(b) } #结果 [999 0 0] [999 0 0]
多维切片
类似于数组,切片可以有多个维度
package main import "fmt" func main() { var a[][]int=make([][]int,2,3) fmt.Println(a) //[[] []] a[0]=make([]int,2,3) fmt.Println(a) //[[0 0] []] }
多维数组初始化并赋值
package main import "fmt" func main() { var a [][]string=[][]string{{"1","2"},{"3","4"}} fmt.Println(a) fmt.Println(len(a)) fmt.Println(cap(a)) a[0][1]="999" fmt.Println(a) } #结果 [[1 2] [3 4]] 2 2 [[1 999] [3 4]]