• Go从入门到精通——函数——可变参数——参数数量不固定的函数形式


    可变参数——参数数量不固定的函数形式

      Go 语言支持可变参数特性,函数声明和调用时没有固定数量的参数,同时也提供了一套方法进行可变参数的多级传递。

      Go 语言的可变参数格式如下:

    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)

    // 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 在使用时,传入的值类型不受限制,例如:

    fmt.Println(5,"Hello", &struct{a int}{1},true)
    

      2. 部分参数是可变参数:fmt.Printf (go version go1.18.1 windows/amd64)

      fmt.Printf 的第一个参数为参数列表,后面的参数是可变参数,fmt.Printf 函数的格式如下:

    // 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,后面的参数变量可以变化,使用时候,代码如下:

    fmt.Printf("pure string\n")
    fmt.Printf("value: %v %f\n", true, math.Pi)

     二、遍历可变参数列表——获取每一个参数的值

      可变参数列表的数量不固定,传入的参数是一个切片。如果需要获得每一个参数的具体值时,可以对可变参数变量进行遍历。

    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()函数,该函数将分别为不同的参数打印它们的值和类型的详细描述。

    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))
    }

      代码运行结果:

    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
    

    四、在多个可变参数函数中传递参数

      可变参数变量是一个包含所有参数的切片,如果要在多个可变参数中传递参数,可以在传递时在可变参数变量中默认添加 "...",将切片中的元素进行传递,而不是传递可变参数变量本身。

    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)
    }
  • 相关阅读:
    vid = two 切开 分开 两个眼睛 还有看的含义 词根
    ACS 构词法 + 44个后缀 记忆方法
    测试打包失败 已解决 分析过程 关键字 Jenkins nexus packagelock.json npm install build
    RBAC 介绍,案例讲解
    为什么Dapr是比SpringCloud和Istio更优雅的微服务框架?
    SmartIDE v0.1.18 已经发布 助力阿里国产IDE OpenSumi 插件安装提速10倍、Dapr和Jupyter支持、CLI k8s支持
    Then Swift 初始化对象语法糖
    javaGUI 最基础的界面 标签、输入框、按钮、事件处理 模板
    2019百度之星第三场 最短路2
    2021百度之星初赛第二场 魔怔
  • 原文地址:https://www.cnblogs.com/zuoyang/p/16320719.html
Copyright © 2020-2023  润新知