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)
}
    原文作者:任性的萝卜
    原文地址: https://blog.csdn.net/weixin_44373940/article/details/104425825
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞