48.slice相关知识点
slice的中文意思是切片。
要想理解切片,我们首先要理解数组。
数组是一个长度不能变化的容器,存储同一数据类型的数据。
比如:int数组
[1,2,3,4,5,6]
切片是对数组中一截,一小段,一个子集的地址的截取,切片存储的是它指向的底层数组中的一小截数据的地址,切片中不存数据,创建切片也不会把数组中的数据copy一份,切片只是存储着数组中一部分连续的数据的地址,切片的每一个元素实际上都指向具体的数组的中一个元素。
切片内部包含三个元素:
1.底层数组(它指向的是哪一个数组)
我们要理解底层数组是什么,先举例:
[1,2,3]这是一个int数组,其中元素1 的地址是 0x0001,元素2的地址是0x0002,元素3的地址是0x0003。
那么如果我们创建一个通过数组[1,2,3]创建一个切片x。
这个x里面存储的并不是拷贝的另外一份新的[1,2,3]。
切片x实际上是这样子的:
[0x0001,0x0002,0x0003]
当我们取出x[0] [1,2,3]中的1的地址。
也就是说,当我们修改了数组[1,2,3] [0]实际上还是0x0001,所以此时取出x[0],得到的就是5。
切片存储的每一个元素实际上是它指向的底层数组的每一个元素的地址。
也就是说切片是一个引用类型,它不存储元素,不拷贝元素,它存储数组元素的引用,通过修改切片会修改原来数组的值。
2.切片的长度
这个切片中有有几个元素,指向了数组中的几个连续的元素。
3.切片的容量
从切片在底层数组的起始下标(切片的首个元素)到底层数组的最后一个元素,一共有几个元素,切片的容量就是几。
例如:(下面先用伪代码示例,后面有具体可执行代码)
原数组:a = [1,2,3,4,5,6,7,8]
切片: b = a[2:5] 从数组a的下标为2的开始,也就是具体数值是3开始,截取到下标为5,下标为5的是6,因为切片截取是左开右闭,所以切片中包括下标为2的数值3,不包含下标为5的数值6。
切片存储的地址指向的数据是:[3,4,5]
因为3,4,5有三个数,所以切片的长度是3。
因为从切片的起始元素3到底层数组的末尾元素8之间有6个元素,所以切片的容量是6。
修改切片实际上是修改切片指向的底层数组中的值。
49.Go中类似于函数指针的功能
Go中要实现函数指针非常简单。
因为Go中的函数也是一种类型。
所以我们只要声明一个变量,把某一个函数赋值给这个变量,就能实现函数指针的效果。
如下代码示例:
package main
import "fmt"
//加法
func myAddFun(x,y int) int {
return x+y
}
//减法
func mySubFun(x,y int ) int{
return x-y;
}
//函数变量(类似于函数指针)
var myPointFun func(x,y int) int
func main() {
//加法函数赋值给该函数变量,相当于函数指针指向加法函数
myPointFun = myAddFun
fmt.Printf("a+b = %d\n",myPointFun(10,20))
//减法函数赋值给该函数变量,相当于函数指针指向减法函数
myPointFun = mySubFun
fmt.Printf("a-b = %d\n",myPointFun(100,50))
}
输出:
a+b = 30
a-b = 50