golang学习笔记——数组与切片

数组:

*go中数组是值类型,数组作为参数时是进行的值拷贝

数组创建方式:

package main

import "fmt"

func main() {
   //数组定义方式
   
   //数组的长度必须为数值常量  
   var arr [3]int
   //var i int = 0
   //var ai [i]int
   arr[0] = 1
   arr[1] = 10
   arr[2] = 22
   fmt.Println(arr)

   var arr2 = [3]int{2, 4, 6}
   fmt.Println(arr2)

   //有编译器自动识别数组长度 
   var arr3 = [...]int{5, 7, 8}
   fmt.Println(arr3) 
   //可以定义空数组,但无实际价值
   arr4 := [...]int{}
   fmt.Println("arr4 len:", len(arr4))
   //arr4[0] = 0 //编译报错,下标越界

   //指定下标和对应的值
   arr5 := [3]int{0:9, 1:8, 2:7} 
   fmt.Println("arr5 ", arr5)
   arr6 := [...]int{4:101}
   fmt.Println("arr6", arr6)

   //new 为内建函数 返回值为对应指针
   arr7Point := new([3]int)
   fmt.Printf("arr7Point type %T \n", arr7Point)
   (*arr7Point)[0] = 256
   (*arr7Point)[1] = 26
   (*arr7Point)[2] = 356
   fmt.Printf("*arr7Poiont  %v  ; len= %v \n", *arr7Point, len(*arr7Point))
}

*数组的指针指向的是数组第一个元素的地址,即数组的指针==数组第一个元素的指针

*go中同数据类型元素的不同长度的数组认为非同类型数组

*通过for 或 for - range遍历数组

package main

import (
    "fmt"
)

func main() {
    arr1 := [4]int{1, 2, 3, 4}
    fmt.Printf("arr1 address -- %p , arr1[0] address -- %p \n", &arr1, &arr1[0])
    //通过指针可以计算对应元素的位置
    //64位os,int为64位即8个字节,数组内存是连续的,
    //arr1[0]的地址加8字节即为arr[1]的位置
    fmt.Printf("arr1[0] address -- %p, arr1[1] address -- %p \n", &arr1[0], &arr1[1])
    arr2 := [...]int{1, 2}
    
    foreachLen4(arr1)
    fmt.Println(arr1)
    foreachLen2(arr2)
    //foreachLen2(arr1) //编译报错
    //foreachLen4(arr2) //编译报错
}

func foreachLen4(arr [4]int) {
    for i := 0; i < len(arr); i++ {
        fmt.Println("foreachLen4 - ", arr[i])
        //go中数组为值类型 进行值拷贝
        arr[i] = arr[i] + 1
    }
}

func foreachLen2(arr [2]int) {
    //range 可将数组下标和对应的值返回, 通过下划线 可以忽略 下标或值
    // for _, val := range arr
    // for idx, _ := range arr
    for idx, val := range arr {
        fmt.Printf("foreachLen2: idx -- %v, val -- %v \n", idx, val)
    }
}

 

切片slice

*go中特有的数据类型切片类似可变数组,切片持有对应数组的元素指针

package main

import "fmt"

func main() {
    //指针的创建
    var arr [5]int = [5]int{1, 2, 3, 4, 5}
    //从数组映射 数组[起始下标 : 截止下标], 含头不含尾
    //注意[]int中“[]”无数字
    var slice []int= arr[1:3]
    fmt.Println("slice ", slice)
    //当起始下标为0 ,或截止下标为对应数组长度时可省略
    slice2 := arr[:3]
    slice3 := arr[1:]
    slice4 := arr[:]
    fmt.Println("slice2: ", slice2, " slice3: ", slice3, " slice4:", slice4)

    //切片中的元素对应映射数组元素的指针
    fmt.Printf("arr addr -- %p, arr[1] addr -- %p , arr[2] addr -- %p \n",
            &arr, &arr[1], &arr[2])
    fmt.Printf("slice addr -- %p, slice[0] addr -- %p, slice[1] addr -- %p \n ",
            &slice[0], &slice[1])

    //make 为内建函数,创建应用类型
    //make(切片类型, 初始长度, 初始容量)
    slice5 := make([]int, 3, 6)
    slice5[0] = 99
    slice5[1] = 88
    slice5[2] = 77

    //切片有长度 与 容量属性,容量随元素个数的增加而自动扩充,内建函数cap可获得容量
    fmt.Printf("slice5 len %v , cap %v", len(slice5), cap(slice5))

    fmt.Println("slice5", slice5)
    //切片虽为可变长,但增加超过初始长度的元素时不可通过下标直接赋值,需使用内建函数append
    //    slice5[3] = 66 //编译报错 越界
    //append 会返回扩充后的切片
    slice5 = append(slice5, 66)
    fmt.Println("slice5 --", slice5)
    //可以append对应类型切片,但不可append数组 ==》类型不匹配
    slice5 = append(slice5, slice...)
    // slice5 = append(slice5, arr...) //编译报错
    fmt.Println("slice5 ** ", slice5)
}

切片扩容

package main

import (
    "math/rand"
    "time"
    "fmt"
)

func main() {
    slice := make([]int, 5, 10)
    //slice 是引用类型
    generate(slice)
    fmt.Println("slice ", slice)
    
    arr := [5]int{1, 2, 3, 4, 5}
    slice2 := arr[:]
    fmt.Println("slice2: ", slice2, "arr ", arr)
    fmt.Println("slice2 addr: ", &slice2, "arr addr:", &arr)
    generate(slice2)
    //切片是数组元素的引用,故切片改变会导致原数组改变,反过来也是
    //虽然元素对应的值发生变化,但元素对应的指针并未发生变化
    //(开辟的空间可以存放对应的数据类型)
    //切片可以理解成是由 对应数组元素的指针组成的数组 + 长度属性 + 容量属性 的结构
    fmt.Println("slice2 -- ", slice2, "arr -- ", arr)
    fmt.Println("slice2 --addr ", &slice2, "arr --addr ", &arr)
    fmt.Printf("arr len %v , slice2 len %v \n", 
                len(arr), len(slice2))
    //append带来的改变    
    slice3 := append(slice2, 6)
    fmt.Printf("arr add - %p, slice2 add - %p, slice3 add - %p \n", 
                &arr, &slice2, &slice3)
    //append 是将原有切片对应的元素的值拷贝到新的地址,故而新切片元素对应的指针发生改变
    //append是重新分配内存空间
    fmt.Printf("arr len %v , slice2 len %v, slice3 len %v \n", 
                len(arr), len(slice2), len(slice3))
    fmt.Printf("arr[1] add %p, slice2[1] add %p, slice3[1] add %p \n",
                &arr[1], &slice2[1], &slice3[1])
    

}

func generate(slice []int) {
    //设置随机因子
    rand.Seed(time.Now().UnixNano())
    for i := 0; i < 5; i++ {
        slice[i] = rand.Intn(100)
    }
}

切片append与切片容量

*一个大坑:

*通过数组映射过来的切片长度与容量一致,make声明切片时可省略容量此时默认容量与长度一致;

*切片append所返回的新切片会共用原切片所定义的容量范围内的空间,即在append的元素不超过设定的容量时,新的切片元素的指针与原有切片元素的指针 指向的是同一个地址,当超出容量时则指向不同的地址

package main

import (
    "fmt"
)

func main() {
    //容量
    arr := [3]int{1, 2, 3}
    s := arr[:]
    fmt.Println("s = ", s, " len ", len(s), " cap ", cap(s))

    s1 := make([]int, 3)
    fmt.Println("s1 = ", s1, " len ", len(s1), " cap ", cap(s1))
	fmt.Println("-----------------------------")

    //
	slice := make([]int, 2, 3)
	slice[0] = 8
	slice[1] = 88
	fmt.Printf("slice地址:%p  slice[0]地址:%p slice[1]地址:%p \n", &slice, &slice[0], &slice[1])

	fmt.Println("-----------slice append 9 ==> slice2------------------")
	slice2 := append(slice, 9)
	fmt.Println("slice = ", slice, " len ", len(slice), " cap ", cap(slice))
	fmt.Printf("slice地址:%p  slice[0]地址:%p slice[1]地址:%p \n", &slice, &slice[0], &slice[1])
	fmt.Println("slice2 = ", slice2, " len ", len(slice2), " cap ", cap(slice2))
	fmt.Printf("slice2地址:%p  slice2[0]地址:%p slice2[1]地址:%p slice2[1]地址:%p \n",
			 &slice2, &slice2[0], &slice2[1], &slice2[2])

	//slice2 append超过 slice 的容量时 slice2元素的地址就与slice不一致 
	// fmt.Println("-----------slice2 append ==> slice2------------------")
	// slice2 = append(slice2, 99)
	// fmt.Println("slice = ", slice)
	// fmt.Printf("slice地址:%p  slice[0]地址:%p slice[1]地址:%p \n", &slice, &slice[0], &slice[1])
	// fmt.Println("slice2 = ", slice2)
	// fmt.Printf("slice2地址:%p  slice2[0]地址:%p slice2[1]地址:%p slice2[2]地址:%p slice2[3]地址:%p\n",
	// 		 &slice2, &slice2[0], &slice2[1], &slice2[2], &slice2[3])

	fmt.Println("-----------slice append 100 ==> slice------------------")
	slice = append(slice, 100)
	fmt.Println("slice = ", slice, " len ", len(slice), " cap ", cap(slice))
	fmt.Printf("slice地址:%p  slice[0]地址:%p slice[1]地址:%p slice[2]地址:%p \n",
			 &slice, &slice[0], &slice[1], &slice[2])
	fmt.Println("slice2 = ", slice2, " len ", len(slice2), " cap ", cap(slice2))	 
	fmt.Printf("slice2地址:%p  slice2[0]地址:%p slice2[1]地址:%p slice2[2]地址:%p \n",
			 &slice2, &slice2[0], &slice2[1], &slice2[2])
				 
	fmt.Println("-----------slice append 20 ==> slice-----超过容量-------------")
	slice = append(slice, 20)
	fmt.Println("slice = ", slice, " len ", len(slice), " cap ", cap(slice))
	fmt.Printf("slice地址:%p  slice[0]地址:%p slice[1]地址:%p slice[2]地址:%p slice[3]地址:%p \n",
			&slice, &slice[0], &slice[1], &slice[2], &slice[3])
	fmt.Println("slice2 = ", slice2, " len ", len(slice2), " cap ", cap(slice2))	 
	fmt.Printf("slice2地址:%p  slice2[0]地址:%p slice2[1]地址:%p slice2[2]地址:%p \n",
			&slice2, &slice2[0], &slice2[1], &slice2[2])
    

}

string 与切片以及rune

package main

import (
    "fmt"
)

func main() {
	//string 底层是byte数组,且该数组不可变
	str := "hello,独角兽!"
	fmt.Println(str)
	strSlice := str[:5]
	fmt.Println("截取:", strSlice)
	//因string对应的byte数组不可变,故而str对应的切片中的元素也不可以重新赋值
	// strSlice[0] = 'A' 

	//通过byte数组来改变
	bytes := []byte(str)
	bytes[0] = 'A'
	newStr := string(bytes)
	fmt.Println("str -- ", str, " newStr --", newStr)

	//因go为utf8编码,byte对应一个字节,汉字为三个字节,无法放入单个字节
	//rune的定义:32位有符号整形,int32的别名;将string转换成rune数组时
	//解决了汉字长度的问题
	// bytes[0] = '我'
	//rune 按照字符处理string
	strRune := []rune(str)
	strRune[0] = '我'
	newStr = string(strRune)
	fmt.Println(newStr)

}

 

 

 

 

 

 

 

基于STM32F407,使用DFS算法实现最短迷宫路径检索,分为三种模式:1.DEBUG模式,2. 训练模式,3. 主程序模式 ,DEBUG模式主要分析bug,测量必要数据,训练模式用于DFS算法训练最短路径,并将最短路径以链表形式存储Flash, 主程序模式从Flash中….zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值