最近学习 go 的过程中遇到了一个 content = append(content, buf[:n]...) 的用法,对...这个东西有点疑惑,然后查询了下资料才明白是怎么回事,在 Go 语言中,函数签名 func append(slice []Type, elems ...Type) []Type 中的三个点 ... 表示 变长参数(variadic parameter)。下面详细解释这个函数签名:
变长参数(Variadic Parameter)
1.语法结构
func append(slice []Type, elems ...Type) []Type
2.功能说明
- slice 是一个类型为 []Type 的切片,它是第一个参数。
- elems 是一个类型为 …Type 的变长参数列表。
- 函数返回一个新的切片 []Type。
变长参数详解
变长参数的定义
- 变长参数的定义
- 在函数参数列表中,最后一个参数可以使用 … 来定义一个变长参数。
- 这意味着调用者可以传入任意数量的 Type 类型的参数。
- 内部处理
- 在函数内部,变长参数 elems …Type 被当作一个类型为 []Type 的切片来处理。
- 可以通过索引或循环遍历来访问这些参数。
示例代码(普通用法)
package main
import "fmt"
// 定义一个简单的 append 函数
func append(slice []int, elems ...int) []int {
return append(slice, elems...)
}
func main() {
// 原始切片
originalSlice := []int{1, 2, 3}
// 使用变长参数追加元素
newSlice := append(originalSlice, 4, 5, 6)
fmt.Println(newSlice) // 输出: [1 2 3 4 5 6]
}
解释
- 调用方式
- 调用 append 函数时,可以传入任意数量的 int 类型参数。
- 在上述示例中,append(originalSlice, 4, 5, 6) 将 4, 5, 6 作为单独的参数传递给 append 函数。
- 内部处理
- 在 append 函数内部,elems …int 被当作一个 []int 类型的切片处理。
- 使用 append 内置函数将 originalSlice 和 elems 合并成一个新的切片。
示例代码(其它用法)
package main
import (
"fmt"
"io"
"os"
)
func main() {
// 打开文件
file, err := os.Open("./xxx.txt")
if err != nil {
fmt.Println("open file err :", err)
return
}
defer file.Close()
// 定义接收文件读取的字节数组
var buf [128]byte
var content []byte
for {
n, err := file.Read(buf[:])
if err == io.EOF {
// 读取结束
break
}
if err != nil {
fmt.Println("read file err ", err)
return
}
content = append(content, buf[:n]...)
}
fmt.Println(string(content))
}
这个案例中需要注意的是 在 buf[:n] 后面加上 ... 表示将 buf[:n] 中的所有元素作为单独的参数传递给 append 函数,而不是作为一个整体的切片参数,这样做的效果就是将 buf[:n] 中的所有元素追加到 content 切片的末尾。如果 buf[:n] 包含多个元素,这些元素会逐个添加到 content 中
,例如:
content := []int{1, 2, 3}
buf := []int{4, 5, 6, 7, 8}
n := 3
content = append(content, buf[:n]...)
fmt.Println(content) // 输出: [1 2 3 4 5 6]
在这个例子中,buf[:n] 等于 [4, 5, 6],这三个元素被追加到了 content 中。