第八课 go语言基础-数组、切片和map
tags:
- golang
- 2019尚硅谷
categories:
- golang
- 数组
- 切片
- 二维数组
- map
文章目录
第一节 go语言的数组
1.1 数组定义
- 数组可以存放多个同一类型数据。数组也是一种数据类型,在Go中,数组是值类型。
- 数组的定义
- var 数组名 [数组大小]数据类型比如:var a [5]int
- 赋初值a[0]=1 a[1]=30 …
- 数组在内存布局(重要)
- 数组的地址可以通过数组名来获取&intArr
- 数组的第一个元素的地址,就是数组的首地址
- 数组的各个元素的地址间隔是依据数组的类型决定,比如int64->8 int32->4…
package main
import "fmt"
/*
[0 0 0]
[10 20 30]
intArr的地址=0xc0420520a0 intArr[0] 地址0xc0420520a0 intArr[1] 地址0xc0420520a8 intArr[2] 地址0xc0420520b0PS
*/
func main() {
var intArr [3]int //int占8个字节
//当我们定义完数组后,其实数组的各个元素有默认值0
fmt.Println(intArr)
intArr[0] = 10
intArr[1] = 20
intArr[2] = 30
fmt.Println(intArr)
fmt.Printf("intArr的地址=%p intArr[0] 地址%p intArr[1] 地址%p intArr[2] 地址%p",
&intArr, &intArr[0], &intArr[1], &intArr[2])
}
1.2 数组使用
- 访问数组元素 数组名[下标] 比如:你要使用a数组的第三个元素a[2]
- 四种初始化数组的方式
//四种初始化数组的方式
var numArr01 [3]int = [3]int{
1, 2, 3}
fmt.Println("numArr01=", numArr01)
var numArr02 = [3]int{
5, 6, 7}
fmt.Println("numArr02=", numArr02)
//这里的 [...]是规定的写法
var numArr03 = [...]int{
8, 9, 10}
fmt.Println("numArr03=", numArr03)
var numArr04 = [...]int{
1: 800, 0: 900, 2:999}
fmt.Println("numArr04=", numArr04)
//类型推导
strArr05 := [...]string{
1: "tom", 0: "jack", 2:"mary"}
fmt.Println("strArr05=", strArr05)
- 数组的遍历
- 常规遍历
- for- range结构遍历
- 第一个返回值index是数组的下标
- 第二个value是在该下标位置的值
- 他们都是仅在for循环内部可见的局部变量
- 遍历数组元素的时候,如果不想使用下标index,可以直接把下标index标为下划线_
- index和value的名称不是固定的,即程序员可以自行指定,一般命名为index和value
for index, value := range array01 {
...
}
//演示for-range遍历数组
heroes := [...]string{
"宋江", "吴用", "卢俊义"}
//使用常规的方式遍历
for i := 0; i < len(heroes); i++{
fmt.Printf("常规方式遍历heroes[%d]=%v\n", i, heroes[i])
}
//for-range遍历数组
for i, v := range heroes {
fmt.Printf("i=%v v=%v\n", i, v)
fmt.Printf("for-range遍历heroes[%d]=%v\n", i, heroes[i])
}
for _, v := range heroes {
fmt.Printf("for-range遍历元素的值=%v\n", v)
}
1.3 数组使用的注意事项和细节
- 数组是多个相同类型数据的组合,一个数组一旦声明/定义了,其长度是固定的,不能动态变化
- var arr []int这时arr就是一个slice切片
- 数组中的元素可以是任何数据类型,包括值类型和引用类型,但是不能混用。
- 数组创建后,如果没有赋值,有默认值(零值)
- 使用数组的步骤
- 1.声明数组并开辟空间
- 2给数组各个元素赋值(默认零值)
- 3使用数组
- 数组的下标是从0开始的
- 数组下标必须在指定范围内使用,否则报panic:数组越界,比如var arr [5]int则有效下标为0-4
- Go的数组属值类型, 在默认情况下是值传递, 因此会进行值拷贝。数组间不会相互影响
- 如想在其它函数中,去修改原来的数组,可以使用引用传递(指针方式)
- 长度是数组类型的一部分,在传递函数参数时需要考虑数组的长度
arr := [3]int{
11, 22, 33}
// 值传递
test(arr)
fmt.Println(arr)
// 把数组的地址传过来
test01(&arr)
fmt.Println(arr)
// 直接传递数组 值传递 复制一份数组
func test(arr [3]int) {
arr[0] = 88
}
// 把数组的地址传过来
func test01(arr *[3]int) {
(*arr)[0] = 88
}
第二节 go语言的切片
2.1 切片的基本介绍
- 切片的英文是slice
- 切片是数组的一个引用,因此切片是引用类型,在进行传递时,遵守引用传递的机制。
- 切片的使用和数组类似,遍历切片、访问切片的元素和求切片长度len(slice)都一样。
- 切片的长度是可以变化的,因此切片是一个可以动态变化数组。
- 切片定义的基本语法:
- var 切片名 []类型 比如: var a []int
- slice从底层来说,其实就是一个数据结构(struct结构体)
type slice struct {
ptr *[2]int
len int
cap int
}
- 切片的具体使用的三种方式
- 第一种方式: 定义一个切片,然后让切片去引用一个已经创建好的数组
- 第二种方式: 通过make来创建切片
- 基本语法: var 切片名 []type = make([]type, len, [cap])
- 参数说明: type:就是数据类型len: 大小cap :指定切片容量,可选,如果 你分配了cap,则要求cap>=len
- 第三种方式: 定义一个切片,直接就指定具体数组,使用原理类似make的方式
- 注意:
- 通过make方式创建切片可以指定切片的大小和容量
- 如果没有给切片的各个元素赋值,那么就会使用默认值[int, float=>0 string =>"" bool=>false]
- 通过make方式创建的切片对应的数组是由make底层维护,对外不可见,即只能通过slice去访问各个元素.
- 面试题:方式1和方式2
- 方式1是直接引用数组,这个数组是事先存在的,程序员是可见的。.
- 方式2是通过make来创建切片,make也会创建一个数组,是由切片在底层进行维护,程序员是看不见的。
package main
import "fmt"
func main() {
var arr [5]int = [...]