07-数组和切片

数组

数组是同一类型元素的集合。例如,整数集合 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]]
posted @ 2019-12-10 22:05  只会玩辅助  阅读(241)  评论(0编辑  收藏  举报