💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 一、Golang 可变参数 函数方法的参数,可以是任意多个,这种我们称之为可以变参数,比如我们常用的fmt.Println()这类函数,可以接收一个可变的参数。 可以变参数,可以是任意多个。我们自己也可以定义可以变参数,可变参数的定义,在类型前加上省略号…即可。 ~~~go func main() { print("1","2","3") } func print (a ...interface{}){ for _,v:=range a{ fmt.Print(v) } fmt.Println() } ~~~ ## 二、Slice和数组的对比 在 Go 中,与 C 数组变量隐式作为指针使用不同,Go 数组是值类型,赋值和函数传参操作都会复制整个数组数据。假想每次传参都用数组,那么每次数组都要被复制一遍。如果数组大小有 100万,在64位机器上就需要花费大约 800W 字节,即 8MB 内存。这样会消耗掉大量的内存。 于是乎有人想到,函数传参用数组的指针。这样更加高效的利用内存,性能也比之前的好。 不过传指针会有一个弊端,万一原数组的指针指向更改了,那么函数里面的指针指向都会跟着更改。 切片的优势也就表现出来了。用切片传数组参数,既可以达到节约内存的目的,也可以达到合理处理好共享内存的问题。打印结果第二行就是切片,切片的指针和原来数组的指针是不同的。 并非所有时候都适合用切片代替数组,因为切片底层数组可能会在堆上分配内存,而且小数组在栈上拷贝的消耗也未必比 make 消耗大。 ## 三、Golang Slice的底层实现 切片是基于数组实现的,它的底层是数组,它自己本身非常小,可以理解为对底层数组的抽象。因为基于数组实现,所以它的底层的内存是连续分配的,效率非常高,还可以通过索引获得数据,可以迭代以及垃圾回收优化。 切片本身并不是动态数组或者数组指针。它内部实现的数据结构通过指针引用底层数组,设定相关属性将数据读写操作限定在指定的区域内。切片本身是一个只读对象,其工作机制类似数组指针的一种封装。 切片对象非常小,是因为它是只有3个字段的数据结构: 指向底层数组的指针 切片的长度 切片的容量 这3个字段,就是Go语言操作底层数组的元数据。 ## 四、Golang Slice的扩容机制,有什么注意点? Go 中切片扩容的策略是这样的: 首先判断,如果新申请容量大于2倍的旧容量,最终容量就是新申请的容量 否则判断,如果旧切片的长度小于1024,则最终容量就是旧容量的两倍 否则判断,如果旧切片长度大于等于1024,则最终容量从旧容量开始循环增加原来的 1/4, 直到最终容量大于等于新申请的容量 [推荐1](https://blog.csdn.net/qq_35526714/article/details/114280569) [推荐2](https://blog.csdn.net/weixin_46305978/article/details/123380358)