GO语言基础知识(二)数组、切片、指针操作

一、指针的应用

二、数组的常见操作

三、切片的常见操作

四、make new内置函数的使用

GO语言中,基本数据类型是值传递,比如int float bool string以及数组和结构体;在进行赋值或者在进行函数参数传递的时候,其实传递的是其值的副本,并非传递的引用(切片、map、chan是引用传递),若要改变这些类型的值,需要使用指针。

<code>n1 := 100
n2 := &n1
//获取指针,得到n1变量对应的带有0x的16进制地址
fmt.Printf("%p \\n",n2)
//根据指针,获得其对应的值
fmt.Printf("%d \\n",*n2)
//根据指针,改变其对应的值
*n2 = 200
//打印查看n1的值
fmt.Printf("%d \\n",n1)/<code>

数组的简单操作

显式指定长度并声明数组后根据下标赋值

<code>var array [10]int
array[0]=1
array[1]=2
fmt.Println(array)/<code>显式指定长度并声明的同时进行初始化

<code>var array1 = [10]int{1,2}
fmt.Println(array1)/<code>隐式指定length,根据后面给的值的个数自动判断length

<code>var array2 = [...]int{1,2,3}


fmt.Println(array2)/<code>隐式指定length并根据下标初始化数组

<code>var array3 = [...]int{2:3,9:10}
fmt.Println(array3,len(array3),cap(array3))
//上面输出 [0 0 3 0 0 0 0 0 0 10] 10 10/<code>数组的遍历

<code>//方式1
for i:=0;i fmt.Print(array3[i])
}
fmt.Println()
//方式2
for i,v:= range array3{
fmt.Printf("%d-%v",i,v)
}/<code>

切片的的基本操作,底层本质是数组,具有自动扩容的能力

<code>var sliceName []int
//声明的切片在使用前必须经过初始化来分配内存否则引发panic异常
fmt.Println("sliceName is nil : ",sliceName==nil) //true
sliceName[0]=1 //抛异常panic/<code>初始化并初始赋值

<code>sliceName = []int{}
//声明长度和容量都是0的切片
fmt.Println("sliceName is nil : ",sliceName==nil) //false
fmt.Println(len(sliceName),cap(sliceName)) //0 0
sliceName = []int{1,2} //声明切片并放入2个元素
fmt.Println(len(sliceName),cap(sliceName)) //2 2/<code>基于数组生成切片

<code>array5 := [...]int{1,2,3,4,5}
sliceName = array5[0:1] //前包含后不包含
fmt.Println(sliceName,len(sliceName),cap(sliceName)) //[1] 1 5
sliceName = array5[1:4] //特殊的可以简写如[1:] [:3] [:]
fmt.Println(sliceName,len(sliceName),cap(sliceName)) //[2,3,4] 3 4
sliceName[0]=999
fmt.Println(sliceName,array5)//改变切片的值会同步影响底层数组的值/<code>

总结:基于数组的切片,容量就是从开始切的位置开始到数组末尾的长度;因为切片的数据是存在底层数组中的,所以改变切边的值必定会影响底层数组的值。

切片再切片

<code>sliceName2 := sliceName[1:2]
fmt.Println(sliceName2,len(sliceName2),cap(sliceName2)) //[3] 1 3
总结:基于切片再切片//容量就是从开始切的位置开始到原底层数组末尾的长度(都是基于底层数组计算的)/<code>

总结:基于切片再切片,容量就是从开始切的位置开始到原底层数组末尾的长度(都是基于底层数组计算的)。

基于make函数构造切片

<code>sliceName3 := make([]int,10,10) //长度和容量都是10的切片
sliceName3[2] =3 //切片赋值
fmt.Println(sliceName3,len(sliceName3),cap(sliceName3))//[0 0 3 0 0 0 0 0 0 0] 10 10
sliceName3 = append(sliceName3,11)
//添加元素有可能会触发切片扩容(原底层数组不足以存储的时候)
//扩容后切片的底层数组就是一个新的,不再是原有的了
fmt.Println(sliceName3,len(sliceName3),cap(sliceName3))//[0 0 3 0 0 0 0 0 0 0 11] 11 20/<code>遍历切片

<code>for i:=0;i< len(sliceName3);i++{
fmt.Print(sliceName3[i])
}
for _,value := range sliceName3 {
fmt.Print(value)
}/<code>复制切片,超过目标切片length以外的数据将不被复制

<code>sliceName4 := make([]int,3,12)
copy(sliceName4,sliceName3)
fmt.Println(sliceName4) //[0 0 3]/<code>删除切片元素

<code>array6 := [10]int{0:1,1:2,9:10}
sliceName5 := array6[:]
fmt.Println("原数组",array6) //[1 2 0 0 0 0 0 0 0 10]
sliceName5 = append(sliceName5[:1],sliceName5[2:]...)
//数组的删除操作会导致底层数组一部分元素复制换位
fmt.Println("原数组",array6) //[1 0 0 0 0 0 0 0 10 10]


fmt.Println(sliceName5,len(sliceName5),cap(sliceName5)) //[1 0 0 0 0 0 0 0 10] len 9 cap 10
sliceName5 = append(sliceName5,11)
fmt.Println("原数组",array6) // [1 0 0 0 0 0 0 0 10 11]
fmt.Println(sliceName5,len(sliceName5),cap(sliceName5)) //[1 0 0 0 0 0 0 0 10 11] 10 10
sliceName5 = append(sliceName5,12)
fmt.Println("原数组",array6)
//原数组 [1 0 0 0 0 0 0 0 10 11] 不再变化,因为原数组长度已不够,新创建了一个数组并扩容
fmt.Println(sliceName5,len(sliceName5),cap(sliceName5)) //[1 0 0 0 0 0 0 0 10 11 12] 11 20/<code>

make new内置函数

make用来初始化slice、map、chan引用类型数据结构并申请内存空间

new用来为基本数据类型比如int、string等申请内存

<code>fmt.Printf("%T\\n",new(int))  //得到int类型的指针*int
fmt.Printf("%T\\n",make(map[string]int,10))//得到一个map的引用/<code>


让我们一起进步学习,共同成长;欢迎大家关注微信公众号:芝麻技术栈