golang中数组与切片的应用

代码加注释撸起来

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)
}

你可能感兴趣的:(Golang)