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)
}
posted @   左扬  阅读(380)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
levels of contents
点击右上角即可分享
微信分享提示