Go从入门到精通——函数——可变参数——参数数量不固定的函数形式
可变参数——参数数量不固定的函数形式
Go 语言支持可变参数特性,函数声明和调用时没有固定数量的参数,同时也提供了一套方法进行可变参数的多级传递。
Go 语言的可变参数格式如下:
1 2 3 | func 函数名(固定参数列表, v...T)(返回参数列表){ 函数体 } |
特性如下:
- 可变参数一般被放置在函数列表的末尾,前面是固定参数列表,当没有固定参数时,所有变量就将是可变参数。
- v为可变参数变量,类型为 []T,也就是拥有多个 T 元素的 T 类型的切片, v 和 T 之间由 "..." 即 3 个点组成。
- T 为可变参数的类型,当 T 为 interface{}时,传入的可以是任意类型。
一、fmt 包中的例子
可变参数有两种形式:所有参数都是可变参数的形式,如 fmt.Println,以及部分是可变参数的形式,如 fmt.Printf,可变参数只能出现在参数的后半部分,因此不可变的参数只能放在参数的前半部分。
1、所有参数都是可变参数:fmt.Println (go version go1.18.1 windows/amd64)
1 2 3 4 5 6 | // Println formats using the default formats for its operands and writes to standard output. // Spaces are always added between operands and a newline is appended. // It returns the number of bytes written and any write error encountered. func Println(a ...any) (n int, err error) { return Fprintln(os.Stdout, a...) } |
fmt.Println 在使用时,传入的值类型不受限制,例如:
1 | fmt.Println(5, "Hello" , & struct {a int}{1},true) |
2. 部分参数是可变参数:fmt.Printf (go version go1.18.1 windows/amd64)
fmt.Printf 的第一个参数为参数列表,后面的参数是可变参数,fmt.Printf 函数的格式如下:
1 2 3 4 5 | // Printf formats according to a format specifier and writes to standard output. // It returns the number of bytes written and any write error encountered. func Printf(format string, a ...any) (n int, err error) { return Fprintf(os.Stdout, format, a...) } |
fmt.Printf()函数在调用时,第一个函数始终必须传入字符串,对应参数是 format,后面的参数变量可以变化,使用时候,代码如下:
1 2 | fmt.Printf( "pure string\n" ) fmt.Printf( "value: %v %f\n" , true, math.Pi) |
二、遍历可变参数列表——获取每一个参数的值
可变参数列表的数量不固定,传入的参数是一个切片。如果需要获得每一个参数的具体值时,可以对可变参数变量进行遍历。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | package main import ( "bytes" "fmt" ) //定义一个函数,参数数量为 0~n,类型约束为字符串 func joinStrings(slist ...string) string { //定义一个字节缓冲,快速地连接字符串 var b bytes.Buffer //遍历可变参数列表 slist,类型为 []string for _, s := range slist { //将遍历出的字符串连续写入字节数组 b.WriteString(s) } //将连接好的字节数组转换为字符串输出 return b.String() } func main() { //输入3个字符串,将他们形成一个字符串 fmt.Println(joinStrings( "ping" , "and" , "rat" )) fmt.Println(joinStrings( "我" , "爱" , "中国" )) } |
三、获得可变参数类型——获得每一个参数的类型
当可变参数为 interface{}类型时,可以传入任何类型的值。此时,如果需要获得变量的类型,可以通过 switch 类型分支获得变量的类型。
下面演示将一系列不同类型的值传入 printTypeValue()函数,该函数将分别为不同的参数打印它们的值和类型的详细描述。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | package main import ( "bytes" "fmt" ) func printTypeValue(slist ... interface {}) string { //字节缓冲作为快速字符串连接 var b bytes.Buffer //遍历参数 for _, s := range slist { //将 interace{} 类型格式化为字符串 str := fmt.Sprintf( "%v" , s) //类型的字符串描述 var typeString string //对 s 进行类型断言 switch s.( type ) { case bool: typeString = "bool" case string: typeString = "string" case int: typeString = "int" } //写值字符串前缀 b.WriteString( "value: " ) //写入值 b.WriteString(str) //写类型前缀 b.WriteString( " type: " ) //写类型字符串 b.WriteString(typeString) //写入换行符 b.WriteString( "\n" ) } return b.String() } func main() { //将不同类型的变量通过 printTypeValue() 打印出来 fmt.Println(printTypeValue(100, "str" , true)) } |
代码运行结果:
1 2 3 4 5 6 7 8 9 10 | Starting: D:\ go -testfiles\bin\dlv.exe dap --check- go -version=false --listen=127.0.0.1:52207 from d:\ go -testfiles DAP server listening at: 127.0.0.1:52207 Type 'dlv help' for list of commands. value: 100 type : int value: str type : string value: true type : bool Process 9212 has exited with status 0 Detaching dlv dap (12820) exited with code: 0 |
四、在多个可变参数函数中传递参数
可变参数变量是一个包含所有参数的切片,如果要在多个可变参数中传递参数,可以在传递时在可变参数变量中默认添加 "...",将切片中的元素进行传递,而不是传递可变参数变量本身。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package main import "fmt" func rawPrint(rawList ... interface {}) { //遍历可变参数切片 for _, a := range rawList { //打印参数 fmt.Println(a) } } //打印函数封装 func print(slist ... interface {}) { //将slist可变参数切片完整传递给下一个函数 rawPrint(slist...) } func main() { print(1, 2, 3) } |
分类:
Go专题精讲
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南