1.数组
1.1数组介绍
- 数组可以存放多个同意类型的数据,数组也是一种数据类型,在go中,数组是值类型
- 定义: var 数组名[数组大小] 数据类型
- var a [5] int
- 赋初值 a[0]=1 a[1]=2
- 数组的地址可以通过数组名来获取&intArr
- 数组的第一个元素的地址,就是数组的首地址
- 数组的各个元素的地址间隔是依据数组的类型决定,比如int64->8 int32->4
1.2数组的使用
● 访问数组元素:数组名[下标] 比如:你要使用a数组的第三个元素 a[2] ● 四种初始化数组的方法
1.3数组的遍历
(1) 常规遍历 (2) for-range遍历 for index,values:= range array{ … } 说明: ○ 第一个返回值index是数组的下标 ○ 第二个返回值value是该下表位置的值 ○ 他们都是仅在for循环内部可用的局部变量 ○ 遍历时,如果不想使用下表用_代替忽略 ○ index,value名称不是固定的,一般为index和value
package main
import (
"fmt"
)
func main(){
arr := [3]int{10,20,30}
for index,value :=range arr{
fmt.Println(index,value)
}
}
1.4数组使用注意事项
● 数组是多个相同类型数据的集合,一个数组一旦声明,其长度是固定的,不能动态变换
● var arr[] int 这是arr就是一个slice切片
● 数组创建后,若没有赋值,有默认值(零值)
○ 数值类型:0
○ 字符串:""
○ bool:false
● 使用数组的步骤:
○ 声明数组并开辟空间
○ 给数组个元素赋值
○ 使用数组
● 数组下标从0开始
● go语言数组属于数值型,在默认情况下是值传递,因此会进行值拷贝,数组间不会相互影响 ● 如果在其他函数中,去修改原来的数组,可以使用引用传递(指针方式) ● 长度是数组类型的一部分,在传递函数参数时,需要考虑数组长度
1.5 随机生成5个数,并反转
2.切片slice
2.1基本介绍
● 切片是数组的一个引用,因此切片是引用类型,在进行传递时,遵守引用传递的机制 ● 切片和数组类似,遍历切片,访问切片的元素和求切片长度len(slice)都一样 ● 切片的长度是可变的,因此切片是一个可以动态变换的数组 ● 切片定义的基本语法: var 切片名 [] 类型 比如:var a[] int
package main
import (
"fmt"
)
func main(){
intArr := [5]int{1,22,33,66,99}
slice :=intArr[1:3]
fmt.Println("intArr=:" ,intArr)
fmt.Println("slice 的内容" , slice)
fmt.Println("slice 长度为" , len(slice))
fmt.Println("slice 的容量为" ,cap(slice))
}
● 内存结构:
● 对上图说明:
○ slice是一个引用类型
○ slice从底层来说是一个数据结构(struct结构体)
type slice struct{
ptr *[2]int
len int
cap int
}
2.2 切片的使用
方式一:引用数组
定义一个切片,然后去引用一个已经创建好的数组,比如上面的方式
方式二:make
通过make来创建切片 基本语法:var 切片名 [] type = make([]type,len,[cap]) 参数说明:type:数据类型 len:大小 cap:指定切片容量,可选,如果分配cap,则cap>=len
package main
import (
"fmt"
)
func main(){
var slice2 []float64 =make([]float64,5,10)
slice2[0]=10
slice2[3]=20
fmt.Println("slice2 的内容" , slice2)
fmt.Println("slice2 长度为" , len(slice2))
fmt.Println("slice2 的容量为" ,cap(slice2))
}
内存 小结: ● 通过make方式创建切片可以指定切片的大小和容量 ● 如果没有给切片的个元素赋值,则为默认值 ● 通过make方式创建的切片对应的数组是由make底层维护的,对外不可见,只能通过slice去访问各个元素
方式三:
定义一个切片,直接就指定具体数组,使用原理类似make方式
package main
import (
"fmt"
)
func main(){
var slice3 []string =[]string{"tom","jack","mary"}
fmt.Println("slice3 的内容" , slice3)
fmt.Println("slice3 长度为" , len(slice3))
fmt.Println("slice3 的容量为" ,cap(slice3))
}
方式一和方式二的区别:
● 方式一是直接引用数组,这个数组是事先存在的,程序员可见的 ● 方式二是通过make来创建切片,make也会创建一个一个数组,是由切片在底层维护,程序员不可见
2.3 切片的遍历
● for循环 ● for-range
2.4 使用注意事项
-
切片初始化时 var slice =arr[startIndex:endIndex] ○ 说明:从arr数组下标为startInde取到endIndex的元素(不包含endIndex) ○ var slice =arr[0:end]可以简写 var slice=arr[:end] ○ var slice =arr[start:len(arr)]可以简写 var slice=arr[start:] ○ var slice =arr[0:len(arr)]可以简写 var slice=arr[:] -
切片初始化时,仍然不能越界,但是可以动态增长 -
cap是一个内置函数,用于统计切片的容量,即最大可以存放多少个元素 -
切片定义完后,还不能使用,因为本身一个空的,需要让其引用到一个数组,或者make一个空间供切片来使用 -
切片可以继续切片
package main
import (
"fmt"
)
func main(){
var slice2 []float64 =make([]float64,5,10)
slice2[0]=10
slice2[3]=20
slice4 := slice2[0:2]
fmt.Println("slice4 的内容" , slice4)
fmt.Println("slice4 长度为" , len(slice4))
fmt.Println("slice4 的容量为" ,cap(slice4))
}
- 用append内置函数,可以对切片进行动态追加
ar slice5 []int=[]int{100,200,300}
slice5 = append(slice5,400,500,600)
fmt.Println("slice5=",slice5)
slice5=append(slice5,slice5...)
fmt.Println("slice5=",slice5)
○ 切片append操作的本质就是对数组扩容 ○ go底层会创建一个新的数组newArr ○ 将slice原来包含的元素拷贝到新的数组newArr中 ○ slice重新引用到newArr ○ 注意newArr是在底层来维护的,程序员不可见
- 切片的拷贝操作
○ 切片使用copy内置函数完成拷贝 ○ copy(slice6,slice5)参数的数据类型都是切片 ○ slice6,slice5的数据空间都是独立的,相互不影响
var slice5 []int=[]int{100,200,300}
slice5 = append(slice5,400,500,600)
fmt.Println("slice5=",slice5)
var slice6 =make([]int,10)
copy(slice6,slice5)
fmt.Println("slice6=",slice6)
- 这段代码没问题,可以运行,输出[1],空间不够不报错
- 切片是引用类型,引用传递
3.string和slice
● string底层是一个byte数组,因此string也可以进行切片处理
str := "wang"
slice:= str[0:2]
fmt.Println(slice)
● string和切片内存形式
● string是不可变的,不能通过str[0]="a"来修改字符串 ● 如果需要修改,可以先将stirng转为[]byte 或[]rune修改完转换为string
str := "wang"
slice:= str[0:2]
fmt.Println(slice)
arr1 := []byte(str)
arr1[0] = 'a'
str=string(arr1)
fmt.Println(str)
如果包含汉字,转为[]rune
str := "wang"
slice:= str[0:2]
fmt.Println(slice)
arr1 := []rune(str)
arr1[0] = '王'
str=string(arr1)
fmt.Println(str)
4.二维数组
4.1 入门
var arr [2][3]int
arr[0][2]=1
arr[1][1]=2
for i:=0;i<2;i++{
for j:=0;j<3;j++{
fmt.Print(arr[i][j]," ")
}
fmt.Println()
}
4.2 使用方式1:先声明,在赋值
● 语法: var 数组名 [大小][大小] 类型 ● 比如 var arr[2][3]int ● 二维数组内存结构
4.3 使用方式2:直接初始化
● var arr [2][3]int = [2][3]int {{1,2,3},{4,5,6}}
● 写法
○ var 数组名 [大小][大小]类型 = [大小][大小] 类型{{值},{值}}
○ var 数组名 [大小][大小]类型 = [...][大小] 类型{{值},{值}}
○ var 数组名= [大小][大小] 类型{{值},{值}}
○ var 数组名 = [...][大小] 类型{{值},{值}}
4.4 二维数组遍历
|