Go语言 可变参数
最近与同事讨论时,提到Go语言的可变参数,之前没有总结过相关知识点,今天我们介绍一下Go语言的可变参数。
可变参数(Variable Parameters):参数数量可变的函数称之为可变参数函数,主要是在使用语法糖(syntactic sugar)。最经典的例子就是fmt.Printf()和类似的函数,fmt.Printf首先接收一个参数,后面可接收若干个参数。
在开始Go语言实例之前,我们先看一下在C语言里面是如何实现可变参数的,如示例:
#include <stdio.h>
#include <stdarg.h>
int sum(int count, ...)
{
    int sum=0;
    int val=0;
    // 定义一个可变参数列表,可以看成是一种特殊的指针类型,list指向的对象是栈上的数据。
    va_list list;
    // 初始化list,list指向第一个被压栈的参数,即函数的最后一个参数,而count则是栈上最后一个参数,系统由此确定栈上参数内存的范围。
    va_start(list, count);
    while(count--)
    {
        // 通过va_arg依次获取参数值,两个参数,一个是指向栈上参数的指针list,
    // 这个指针每取出一个数据移动一次,总是指向栈上第一个未取出的参数,
    // int指需要取出的参数的类型,CPU根据这个类型所占的地址空间来进行寻址。
        val = va_arg(list,int);
        // printf("%d at %X\n", val, &val);
        sum += val;
    }
    //释放list,释放后list置为空。
    va_end(list);
    return sum;
}
int main()
{
    printf("Sum of 1,2,3,4,5 = %d\n", sum(5, 1, 2, 3, 4, 5));
    printf("Sum of 10,20,30 = %d\n", sum(3, 10,20,30));
}运行结果:

我们可以看到,在C语言里面,需要指定参数个数和若干个参数,下面我们介绍一下Go语言中的实现。
实例一:
func1使用的是Go语言的语法糖,按照内部机制来说,...type本质是一个切片,也就是[]type,params被看作是类型为[] int的切片传入func1中,func1可接收任意个int值,返回sum结果。
虽然在可变参数函数内部,...int型参数的行为看起来类似slice,实际上,可变参数函数和切片作为参数的函数是不相同的。
// 可变参数
func func1(params ...int) {
	sum := 0
	for _, param := range params {
		sum += param
	}
	fmt.Println("params : ", params, "\tsum : ", sum)
}调用一:
func TestFunc1(t *testing.T) {
	var params = []int{1, 2, 3}
	func1(params...)
	func1(2, 5)
	func1(2, 5, 8)
}结果一:
=== RUN   TestFunc1
params :  [1 2 3]       sum :  6
params :  [2 5]         sum :  7
params :  [2 5 8]       sum :  15
--- PASS: TestFunc1 (0.00s)
实例二:
func2虽然同样实现了不定参数的功能,但是使用起来比较繁琐,需要[]type{}来构造切片实例。我们可以看到传递的数据是slice,但是在参数传递的时候,我们需要手工初始化slice再传入函数。
// 切片
func func2(params []int) {
	sum := 0
	for _, param := range params {
		sum += param
	}
	fmt.Println("params : ", params, "\tsum : ", sum)
}调用二:
func TestFunc2(t *testing.T) {
	func2([]int{3})
	func2([]int{3, 6})
	func2([]int{3, 6, 9})
}结果二:
=== RUN   TestFunc2
params :  [3]   sum :  3
params :  [3 6]         sum :  9
params :  [3 6 9]       sum :  18
--- PASS: TestFunc2 (0.00s)综上两例,我们可以看出语法糖实现更简洁方便。
实例三:
我们再看一下可变类型的可变参数,见func3:
// 可变类型的可变参数
func func3(params ...interface{}) {
	for _, param := range params {
		switch reflect.TypeOf(param).Kind().String() {
		case "int":
			fmt.Printf("param:%d is an int value!\n", param)
		case "int32":
			fmt.Printf("param:%v is an int32 value!\n", param)
		case "int64":
			fmt.Printf("param:%v is an int64 value!\n", param)
		case "float32":
			fmt.Printf("param:%v is an float32 value!\n", param)
		case "float64":
			fmt.Printf("param:%v is an float64 value!\n", param)
		case "string":
			fmt.Printf("param:%s is an string value!\n", param)
		case "func":
			fmt.Printf("param:%v is an func value!\n", param)
		case "map":
			fmt.Printf("param:%v is an map value!\n", param)
		default:
			fmt.Printf("param:%v is an unknown type.\n", param)
		}
	}
}调用三:
func TestFunc3(t *testing.T) {
	var p1 int = 100 //传递int值
	func3(p1)
	var p2 int32 = 200 //传递int32
	func3(p2)
	var p3 int64 = 300 //传递int64
	func3(p3)
	var p4 = "test string" //传递string
	func3(p4)
	var p5 float32 = 1.11 //传递float32
	func3(p5)
	var p6 float64 = 2.22 //传递float64
	func3(p6)
	var p7 = func(a, b int) int { return a + b } //传递func
	func3(p7)
	var p8 = map[string]string{} ////传递map
	func3(p8)
}结果三:
=== RUN   TestFunc3
param:100 is an int value!
param:200 is an int32 value!
param:300 is an int64 value!
param:test string is an string value!
param:1.11 is an float32 value!
param:2.22 is an float64 value!
param:0x506b50 is an func value!
param:map[] is an map value!
--- PASS: TestFunc3 (0.00s)
PASS总结:
可变参数,主要是Go语言的语法糖之"...type"的使用。
参数个数灵活。
Go语言 可变参数的更多相关文章
- 转:C语言 可变参数
		C语言 可变参数 堆栈一般是怎么压栈处理的 /* * stack space: * * 参数3 | up * 参数2 | * 参数1 v ... 
- C语言 可变参数
		一.基础部分 1.1 什么是可变长参数 可变长参数:顾名思义,就是函数的参数长度(数量)是可变的.比如 C 语言的 printf 系列的(格式化输入输出等)函数,都是参数可变的.下面是 printf ... 
- C语言可变参数函数实现原理
		一.可变参数函数实现原理 C函数调用的栈结构: 可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈. 本 ... 
- 深入C语言可变参数(va_arg,va_list,va_start,va_end,_INTSIZEOF)
		一.什么是可变参数 在C语言编程中有时会遇到一些参数个数可变的函数,例如printf(),scanf()函数,其函数原型为: int printf(const char* format,…),int ... 
- C语言可变参数在宏定义中的应用
		在C语言的标准库中,printf.scanf.sscanf.sprintf.sscanf这些标准库的输入输出函数,参数都是可变的.在调试程序时,我们可能希望定义一个参数可变的输出函数来记录日志,那么用 ... 
- C语言可变参数函数的编写
		1. 引言 C语言我们接触的第一个库函数是 printf(“hello,world!”);其参数个数为1个. 然后,我们会接触到诸如: printf(“a=%d,b=%s,c=%c”,a,b,c);此 ... 
- C语言可变参数va_list
		一.什么是可变参数 在C语言编程中有时会遇到一些参数个数可变的函数,例如printf(),scanf()函数,其函数原型为: int printf(const char* format,-) int ... 
- C语言可变参数
		前段时候在实现利用redis进行的一个数据库比对的功能,稍微去分析了一下redis里面的源代码,然后发现其中的发送命令接口声明如下: void *redisCommand(redisConnect * ... 
- c语言可变参数函数
		c语言支持可变参数函数.这里的可变指,函数的参数个数可变. 其原理是,一般情况下,函数参数传递时,其压栈顺序是从右向左,栈在虚拟内存中的增长方向是从上往下.所以,对于一个函数调用 func(int a ... 
随机推荐
- requests模块使用一
			1.安装与简介 Urllib和requests模块是python中发起http请求最常见的模块,但是requests模块使用更加方便简单. pip install requests 2.GET请求 2 ... 
- Shell中的参数传递
			原文链接 我们先来定义一个方法 function methodName() { paramName1=$1 paramName2=$2 paramName3=$3 # 依此类推,参数是从1开始标号,而 ... 
- Journal of Proteome Research | Clinically Applicable Deep Learning Algorithm Using Quantitative Proteomic Data (分享人:翁海玉)
			题目:Clinically Applicable Deep Learning Algorithm Using Quantitative Proteomic Data 期刊:Journal of Pro ... 
- 【攻防世界】open-source
			难度系数: 3.0 题目来源: Pediy CTF 2018 题目描述:菜鸡发现Flag似乎并不一定是明文比较的 先用:PE查壳,发现没有 
- win7系统下的Nodejs开发环境配置
			此处不推荐使用msi安装包直接安装nodejs,我们应该知道它里面做了哪些事情,这样以后出问题的时候,可以更快速地定位问题点.另一方面,直接安装的情况,以后更新了版本的话会很麻烦,因为如果我们想体验新 ... 
- JSP(二)----指令,注释,内置对象
			## JSP 1.指令 * 作用:用于配置JSP页面,导入资源文件 * 格式: <%@ 指令名称 属性名1=属性值1 属性名2=属性值2 %> <%@ page con ... 
- VScode+phpStudy搭建php代码调试环境
			一.安装Visual Studio Code 官网:https://code.visualstudio.com/ 下载安装包后,按照默认安装即可 安装中文语言环境 点击左侧工具栏的 extension ... 
- 使用条件随机场模型解决文本分类问题(附Python代码)
			对深度学习感兴趣,热爱Tensorflow的小伙伴,欢迎关注我们的网站!http://www.tensorflownews.com.我们的公众号:磐创AI. 一. 介绍 世界上每天都在生成数量惊人的文 ... 
- Python第七章-面向对象高级
			面向对象高级 一. 特性 特性是指的property. property这个词的翻译一直都有问题, 很多人把它翻译为属性, 其实是不恰当和不准确的. 在这里翻译成特性是为了和属性区别开来. 属性是指的 ... 
- coding++:java-HashMap的负载因子为什么默认是0.75?
			本篇文章基于JDK1.8,特在此说明 1):负载因子的作用 负载因子是和扩容机制有关的,意思是如果当前容器的容量,达到了我们设定的最大值,就要开始执行扩容操作.举个例子来解释,避免小白听不懂: 比如说 ... 
