Chapter008 golang中数组和切片

上一章:Chapter007 Golang程序流程控制
下一章:Chapter009 golang中map

一、数组
1、数组的定义
var 数组名 [数组大小] 数组类型
2、数组内存

(1)数组的地址可以通过数组名来获取 &intArr
(2)数组的第一个元素的地址,就是数组的首地址

3、数组初始化
package main
import (
	"fmt"
)

func main()  {

	var numArr01 [3]int = [3]int{1,2,3}
	fmt.Println("numArr01=",numArr01)
	var numArr02 = [3]int {5,6,7}
	fmt.Println("numArr01=",numArr02)
	var numArr03 = [...]int{8,9,10}
	fmt.Println("numArr01=",numArr03)
	var numArr04  = [...]int{1:800,0:900,2:999}
	fmt.Println("numArr01=",numArr04)
	
}

在这里插入图片描述

4、数组遍历

(1)常规遍历 for循环
(2)for-range 遍历访问数组元素
1)语法

for index, value := range arry {
}  //arry是数组

2)说明
1)index————>下标
2)value————>数组下标对应的值
3)index,value是块间变量,出了for块就不能用了
4)index,value不是固定名称,可以自己命名
5)不想要index可以用_占位符代替

5、数组的细节和说明

(1)、数组是相同数据类型的组合,一旦长度定下来,就不能动态改变
(2)、var arr []int 此时arr就是一个slice切片 //没有写大小
(3)、数组中的元素可以是任意类型,包括值类型和引用类型,但是不可以混用
(4)、数组创建后如果没有赋值则是默认值
(5)、下标从0开始
(6)、数组是值类型,数组间不会相互影响
(7)、如果想在其他函数中修改原来的数组,就要使用引用方式(指针方式)
(8)、在传递数组时要传递数组的长度

6、举例

(1)、随机生成5个数,并将其翻转打印
此处需要说明生成随机数函数
在这里插入图片描述

package main

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

func main(){
	var intArr [5]int
	for i:=0;i<len(intArr);i++{
		intArr[i] = rand.Intn(100) //0<n<100
	}
	fmt.Println(intArr)
}

但是此函数若是Seed不变,那么生成的随机数都不会变了,如一直是生成这个
在这里插入图片描述
所以此处要加上我们上一章所学的时间戳来作为Seed种子

package main

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

func main(){
	var intArr [5]int
	rand.Seed(time.Now().UnixNano()) //***********
	for i:=0;i<len(intArr);i++{
		intArr[i] = rand.Intn(100) //0<n<100
	}
	fmt.Println(intArr)
}

此处选择纳秒比较妥当,因为秒相同则Seed还是相同的,所以纳秒相同的几率更小
在这里插入图片描述
下面是进行交换后的完整代码

package main

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

func main(){
	var intArr [5]int
	rand.Seed(time.Now().UnixNano())
	for i:=0;i<len(intArr);i++{
		intArr[i] = rand.Intn(100) //0<n<100
	}

	fmt.Println(intArr)

	//交换
	temp :=0
	for i:=0;i<len(intArr)/2;i++{
		temp = intArr[len(intArr)-1-i]
		intArr[len(intArr)-1-i] = intArr[i]
		intArr[i] = temp
	}
	fmt.Println(intArr)

}

运行结果
在这里插入图片描述

二、切片
1、引言

需要一个数组保存学生的成绩,但是个数不确定,则使用切片(可以暂时理解为动态数组)

2、基本概念

(1)slice
(2)切片是数组的一个引用,在传递时要遵守引用机制
(3)切片的使用和数组类似,遍历切片、访问切片的元素和求切片的长度len(slice)都一样
(4)切片的长度可以变化,因此切片是一个可以动态变化的数组
(5)基本语法

var 变量名[]类型
比如 var a []int
3、举例说明
package main

import (
	"fmt"
)

func main()  {
	//演示切片的使用
	var intArr [5]int = [...]int{1,2,3,4,5}
	//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)
	fmt.Println("slice个数:",len(slice))
	fmt.Println("slice容量:",cap(slice)) 

}

在这里插入图片描述

4、切片内存

在这里插入图片描述
对上图总结:
在这里插入图片描述

5、切片使用的三种方式

(1)定义一个切片,然后让切片去引用一个已经创建好的数组,例如上面的案例
(2)通过make来创建切片
1)基本语法:

var 切片名 []type = make([],len,[cap])

cap 可以不写,若写,那么cap>len
在这里插入图片描述
默认情况下,创建好的切片内元素都为0
访问切片则如

slice[0]

2)举例

package main

import (
	"fmt"
	_ "fmt"
)

func main()  {
	//演示切片的使用 make
	//切片要make后使用
	var slice []float64  =make([]float64,5,10)
	fmt.Println(slice)
	slice[1]=10
	slice[3]=20
	fmt.Println(slice)
	fmt.Println("size=",len(slice))
	fmt.Println("cap=",cap(slice))
}

请添加图片描述

此时就只能通过slice操作元素,而没有数组了
在这里插入图片描述
3)小结:
①通过make创建slice,可以指定切片的大小和容量
②如果没有给切片的各个元素赋值,那么就会使用默认值[int float]——>0;string——>"";bool——>false
③通过make 创建的切片对应的数组是由make底层维护,对外不可见,即只能通过slice操作元素
(3)定义一个切片,直接指定具体数组,原理类似make

	//第三种方式
	var slice3 []string  = []string{"tom","jack","mary"}
	fmt.Println(slice3,len(slice3),cap(slice3))
	

结果:
在这里插入图片描述
(4)使用方式总结:
1)方式1和方式2的区别:
①方式1是直接引用数组,这个数组是直接存在的,程序员是可见的
②方式2是通过make来创建切片,make也会创建一个数组,是由切片在底层进行维护,程序员是看不见的,make创建切片示意图:
在这里插入图片描述

6、切片的遍历

(1)for循环
(2)for-range遍历

package main

import (
	"fmt"
	_ "fmt"
)

func main()  {
	//使用常规for
	var arr [5]int = [...]int{10,20,30,40,50}
	slice :=arr[1:4]
	for i:=0;i<len(slice);i++ {
		fmt.Printf("slice[%v]=%v ", i, slice[i])
	}
	fmt.Print("\n")
	//for-range
	for j,v :=range slice{
		fmt.Printf("slice[%v]=%v ", j, v)
	}
}

两种方式结果
在这里插入图片描述

7、append()内置函数

(1)append内置函数(),可以对切片进行动态增长

	//append()
	var slice2 []int  =[]int{100,200,300}

	//生成新切片
	slice3 := append(slice2, 400)
	fmt.Println("slice3=",slice3)
	
	//改变原来切片
	slice2 = append(slice2,400)
	fmt.Println("slice2=",slice2)

	//切片再追加切片(也可以是其他切片,但是不能是数组)
	slice4 := append(slice2,slice2...)
	fmt.Println("slice4=",slice4)

(2)对上面代码分析
1)append本质是扩容
2)go底层会创建一个新的数组newArr(安装扩容后大小)
3)将slice原来包含的元素拷贝到新的数组newArr
4)slice重新引用到newArr
5)注意newArr是在底层来维护的,程序员不可见

8、copy()函数

切片使用copy函数完成拷贝操作,两切片相互独立不影响。

package main

import "fmt"

func main() {
   var numbers []int
   printSlice(numbers)

   /* 允许追加空切片 */
   numbers = append(numbers, 0)
   printSlice(numbers)

   /* 向切片添加一个元素 */
   numbers = append(numbers, 1)
   printSlice(numbers)

   /* 同时添加多个元素 */
   numbers = append(numbers, 2,3,4)
   printSlice(numbers)

   /* 创建切片 numbers1 是之前切片的两倍容量*/
   numbers1 := make([]int, len(numbers), (cap(numbers))*2)

   /* 拷贝 numbers 的内容到 numbers1 */
   copy(numbers1,numbers)
   printSlice(numbers1)   
}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}
9、切片的细节

(1)切片初始化时,仍然不可以越界,范围在【0,len(arr)-1】之间,但是可以动态增长
(2)简写

1var slice = arr[0:end] ——》 var slice = arr[:end]
2var slice = arr[start:len(arr)] ——》 var slice = arr[start:]
3var slice =arr[0:len(arr)] ——》 var slice = arr[:]

(3)切片定义完后不能直接使用,要引到已经存在的数组或者make后使用
(4)切片可以继续切片

10、string和slice

(1)string是一个byte数组,所以string 可以进行切片操作
(2)string是不可变的,也就是说不可以通过str[0]来修改字符串
(3)如果修改字符串,可以string——>[]byte或者[]rune——>修改——>重写转成string

	
	//string和slice
	str := "hello world"
	slicestr :=str[6:]
	fmt.Print(slicestr)

	//修改字符串 将"hello world"改成"zello world"
	arr1 :=[]byte(str)  //不能处理中文,因为byte是字节,若是中文就会乱码(一个汉字是3个字节)
	arr1[0] = 'z'
	str = string(arr1)
	fmt.Println("\nstr=",str)

	//修改字符串 将"hello world"改成"世界llo world"
	arr2 :=[]rune(str)  //处理中文
	arr2[0] = '世'
	arr2[1] = '界'
	str = string(arr2)
	fmt.Println("\nstr=",str)

在这里插入图片描述

三、二维数组

1、语法

var 数组名 [大小][大小]类型
例如 var arr [2][3]int
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰西啊杰西

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值