文章目录
1. 数组
1.1 数组定义和内存布局
- 定义
var 数组名 [数组大小]数据类型
var a [5]int
- 内存布局
① &intArr可以获取地址
② 第一个元素地址就是数组的首地址
③ 地址间隔由数组类型决定(前一个元素地址,每个元素占用的字节数)
1.2 数组的访问和初始化
- 访问
java一样,下标志访问 - 四种初始化方式
//1.
var numArr01 [3]int = [3]int{1, 2, 3}
//2.
var numArr02 = [3]int{5, 6, 7}
//3.这里的 [...] 是规定的写法
var numArr03 = [...]int{8, 9, 10}
//4.注明下标
var numArr04 = [...]int{1: 800, 0: 900, 2:999}
//类型推导
strArr05 := [...]string{1: "tom", 0: "jack", 2:"mary"}
package main
import (
"fmt"
)
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\n",
&intArr, &intArr[0], &intArr[1], &intArr[2])
//从终端循环输入5个成绩,保存到float64数组,并输出.
// var score [5]float64
// for i := 0; i < len(score); i++ {
// fmt.Printf("请输入第%d个元素的值\n", i+1)
// fmt.Scanln(&score[i])
// }
// //变量数组打印
// for i := 0; i < len(score); i++ {
// fmt.Printf("score[%d]=%v\n", i, score[i])
// }
//四种初始化数组的方式
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)
}
1.3 数组遍历
第一种:常规for int 遍历
第二种:for-range
package main
import (
"fmt"
)
func main() {
//演示for-range遍历数组
heroes := [...]string{"宋江", "吴用", "卢俊义"}
//使用常规的方式遍历,我不写了..
for i, v := range heroes {
fmt.Printf("i=%v v=%v\n", i , v)
fmt.Printf("heroes[%d]=%v\n", i, heroes[i])
}
for _, v := range heroes {
fmt.Printf("元素的值=%v\n", v)
}
}
1.4 数组注意事项
- Go数组默认值传递,进行拷贝数组间不影响,如果相在其他函数中更改原来数组使用引用传递
- 传递数组时要考虑长度
2. 切片
2.1 切片的内存布局
package main
import (
"fmt"
)
func main() {
//演示切片的基本使用
var intArr [5]int = [...]int{1, 22, 33, 66, 99}
//声明/定义一个切片
//slice := intArr[1:3]
//1. slice 就是切片名
//2. intArr[1:3] 表示 slice 引用到intArr这个数组
//3. 引用intArr数组的起始下标为 1 , 最后的下标为3(但是不包含3)
slice := intArr[1:3]
fmt.Println("intArr=", intArr)
fmt.Println("slice 的元素是 =", slice) // 22, 33
fmt.Println("slice 的元素个数 =", len(slice)) // 2
fmt.Println("slice 的容量 =", cap(slice)) // 切片的容量是可以动态变化
fmt.Printf("intArr[1]的地址=%p\n", &intArr[1])
fmt.Printf("slice[0]的地址=%p slice[0==%v\n", &slice[0], slice[0])
slice[1] = 34
fmt.Println()
fmt.Println()
fmt.Println("intArr=", intArr)
fmt.Println("slice 的元素是 =", slice) // 22, 33
}
2.2 切片的使用
- 定义一个切片,引用一个已经创建好的数组,比如前面这个案例
- make创建切片
基本语法:var 切片名 []type = make([]type, len, [cap]) - 定义一个切片直接指定具体数组
package main
import (
"fmt"
)
func main() {
//演示切片的使用 make
var slice []float64 = make([]float64, 5, 10)
slice[1] = 10
slice[3] = 20
//对于切片,必须make使用.
fmt.Println(slice)
fmt.Println("slice的size=", len(slice))
fmt.Println("slice的cap=", cap(slice))
//方式3
fmt.Println()
//第3种方式:定义一个切片,直接就指定具体数组,使用原理类似make的方式
var strSlice []string = []string{"tom", "jack", "mary"}
fmt.Println("strSlice=", strSlice)
fmt.Println("strSlice size=", len(strSlice)) //3
fmt.Println("strSlice cap=", cap(strSlice)) // ?
}
2.3 切片的遍历
- 常规gor
- for-range
2.4 使用注意
- 切片可以继续切片
- append可以对切片进行动态追加
- copy函数可以实现拷贝
package main
import (
"fmt"
)
func main() {
//使用常规的for循环遍历切片
var arr [5]int = [...]int{10, 20, 30, 40, 50}
//slice := arr[1:4] // 20, 30, 40
slice := arr[1:4]
for i := 0; i < len(slice); i++ {
fmt.Printf("slice[%v]=%v ", i, slice[i])
}
fmt.Println()
//使用for--range 方式遍历切片
for i, v := range slice {
fmt.Printf("i=%v v=%v \n", i, v)
}
slice2 := slice[1:2] // slice [ 20, 30, 40] [30]
slice2[0] = 100 // 因为arr , slice 和slice2 指向的数据空间是同一个,因此slice2[0]=100,其它的都变化
fmt.Println("slice2=", slice2)
fmt.Println("slice=", slice)
fmt.Println("arr=", arr)
fmt.Println()
//用append内置函数,可以对切片进行动态追加
var slice3 []int = []int{100, 200, 300}
//通过append直接给slice3追加具体的元素
slice3 = append(slice3, 400, 500, 600)
fmt.Println("slice3", slice3) //100, 200, 300,400, 500, 600
//通过append将切片slice3追加给slice3
slice3 = append(slice3, slice3...) // 100, 200, 300,400, 500, 600 100, 200, 300,400, 500, 600
fmt.Println("slice3", slice3)
//切片的拷贝操作
//切片使用copy内置函数完成拷贝,举例说明
fmt.Println()
var slice4 []int = []int{1, 2, 3, 4, 5}
var slice5 = make([]int, 10)
copy(slice5, slice4)
fmt.Println("slice4=", slice4)// 1, 2, 3, 4, 5
fmt.Println("slice5=", slice5) // 1, 2, 3, 4, 5, 0 , 0 ,0,0,0
}
2.5 String 和 slice
-
String 底层 Byte 数组,可以切片
-
String 和切片在内存的形式
-
String 不可变,不能通过 str[0]=‘z’ 方式修改字符串
-
要修改字符串,先把string——[]byte,或者[]rune——修改——重写成string