代码加注释撸起来
package main
/**
* @Description:数组与切片
* @Author: guai
* @Date:2020/2/21 9:15
**/
import (
"fmt"
"math/rand"
"time"
)
func main() {
//1、数组
//在go语言中数组属于值类型 在默认情况下是值传递,因此作为形参时会进行值拷贝
//且在作为形参时,必须指明数组的长度,只有当形参数的长度与要传递的参数的长度一致才可以成功传值
//1.1、数组的定义及使用
var hens [7]float64
hens[0] = 3.0
hens[1] = 5.0
hens[2] = 4.0
hens[3] = 5.0
hens[4] = 6.0
hens[5] = 7.0
hens[6] = 8.0
totalWeight := 0.0
for i := 0; i < len(hens); i++ {
totalWeight += hens[i]
}
fmt.Println("鸡的总重:", totalWeight)
//1.2、数组定义和内存布局
//定义 var 数组名 [数组大小]数据类型
//1.3、数组在内存中的布局:
//1)数组的地址可以通过数组名来获取 即&hens
//2)数组的一个元素的地址,就是数组的首地址
//3)数组的各个元素的地址间隔时依据数组的类型决定,int64->8 int32->4...
fmt.Printf("hens的地址=%p hens[0]的地址%p hens[1]的地址%p\n", &hens, &hens[0], &hens[1])
//1.3、数组初始化的方式
var numArr [3]int = [3]int{1, 2, 3}
fmt.Println("numArr:", numArr)
var numArr1 = [3]int{1, 2, 3}
fmt.Println(numArr1)
var numArr2 = [...]int{1, 2, 3}
fmt.Println(numArr2)
//通过下标为指定数组的指定位置赋值
var numArr4 = [...]int{1: 8080, 0: 4545, 2: 111}
fmt.Println(numArr4)
//1.4、数组的遍历
//for--range for index, val:=range arry{
// 说明: 第一个返回值index是数组的下标 ,若不想使用 可用 _占位忽略符代替
var strArr = [3]string{"hello ", "world! ", "__乖 "}
for _, val := range strArr {
fmt.Println("for--range 输出字符串:", val)
}
//1.5、数组的应用
//通过循获取一个A-Z的字符数组并输出
var varChars [26]byte
for i := 0; i < len(varChars); i++ {
//将i转为byte类型
varChars[i] = 'A' + byte(i)
}
for i := 0; i < len(varChars); i++ {
fmt.Printf("%c", varChars[i])
}
fmt.Println()
//随机生成五个数并反转打印
var intVarArr [5]int
len := len(intVarArr)
//为使尝产生的随机数不相同需要设置随机种子
rand.Seed(time.Now().UnixNano())
for i := 0; i < len; i++ {
intVarArr[i] = rand.Intn(100)
}
fmt.Println("交换前:", intVarArr)
for i := 0; i < len/2; i++ {
temp := intVarArr[i]
intVarArr[i] = intVarArr[len-i-1]
intVarArr[len-i-1] = temp
}
fmt.Println("交换后:", intVarArr)
//2、切片
//2.1、当用数组保存一组个数不确定的数据时,可使用切片
//1)切片slice 是数组的引用,因此切片是引用类型,
//2)切片的长度可以变化,是一个动态变化数组
//切片定义的基本语法: var 切片名 []类型
//sliece从底层来说是一个结构体(struct)
// type slice struct{
// ptr *[2]int
// len int
// cap int
// }
//2.1、切片的使用一
var intVarArr1 [5]int = [...]int{1, 2, 3, 4, 5}
//定义切片,引用i那天VarArr1数组从0开始到4
slice := intVarArr1[0:5]
fmt.Println("切片的内容:", slice)
fmt.Println("切片的容量;", cap(slice))
//2.2、切片的使用二
//var 切片名 []type =make([]type ,len,[cap]) cap可选
//此方法创建的切片对应的数组有make底层维护,对外不可见,即只能通过slice访问各个元素
var floatSlice []float64 = make([]float64, 10)
floatSlice[1] = 10
floatSlice[9] = 10
fmt.Println("使用make创建slice:", floatSlice, " cap: ", cap(floatSlice))
//2.3、切片的使用三
//定义切片直接指定具体数组,使用原理类似make方式
var strSlice []string = []string{"hello", "world", "_乖"}
fmt.Println("strSlice=", strSlice)
fmt.Println("strSlice cap=", cap(strSlice))
//2.4、切片可以继续切片
var intVarArr2 = [...]int{1, 2, 3}
slice1 := intVarArr2[0:3]
slice2 := slice1[0:3]
fmt.Println("切片的切片:", slice2)
//2.5、使用append内置函数,对切片动态追加
//底层原理分析
//切片append操作本质是对数组扩容
//go底层会创建一个新的数组newArr(大小为扩容后数组的大小)
//将slice原来包含的元素拷贝到新的数组newArr
//最后slice重新引用新的数组
var slice3 []int = []int{1, 2, 3}
fmt.Println("slice的动态追加:", slice3, " cap:", cap(slice3))
slice3 = append(slice3, 1, 2, 3)
fmt.Println("slice的动态追加:", slice3, " cap:", cap(slice3))
//2.6、切片的拷贝操作
//切片使用copy内置函数完成copy
//当目标slic的长度小于源slice的长度时,只copy目标长度的内容
//如 下:
var slice4 []int = []int{1, 2, 3}
//只copyslice中的前两个元素
var slice5 = make([]int, 2)
copy(slice5, slice4)
slice5[0] = 0
fmt.Println("切片的copy:slice4:", slice4, " slice5", slice5)
//若直接使用赋值符号:
slice5 = slice4
slice5[0] = 0
fmt.Println("切片的直接复制:slice4:", slice4, " slice5", slice5)
//通过对比结果会发现,使用赋值符号是,时将slice5指向slice4指向的内存,当修改slice5时修改的时它们公用的内存
//而copy则是为slice5开辟了新的内存空间然后将slice4的值copy到新的内存空间中
//3、string和slice
//string底层是一个byte数组,因此string也可以进行切片处理
//[:]表示下标从0开始到最后
//[a:] 表示从a开始到最后
//[:a]从0开始到a
str := "hello world!"
slice6 := str[:]
fmt.Println("slice6:", slice6)
}