了解golang的不定参数(... parameters),这一篇就够了

在实际开发中,总有一些函数的参数个数是在编码过程中无法确定的,比如我们最常用的fmt.Printf和fmt.Println:

fmt.Printf("一共有%v行%v列\n", rows, cols)
fmt.Println("共计大小:", size)

当你需要实现类似的接口时,就需要我们的不定参数出场了。

golang的不定参数

顾名思义,不定参数就是一个占位符,你可以将1个或者多个参数赋值给这个占位符,这样不管实际参数的数量是多少,都能交给不定参数来处理,我们看一下不定参数的声明:

func Printf(format string, a ...interface{}) (n int, err error)
func Println(a ...interface{}) (n int, err error)

不定参数使用name ...Type的形式声明在函数的参数列表中,而且需要是参数列表的最后一个参数,这点与其他语言类似;

不定参数在函数中将转换为对应的[]Type类型,所以我们可以像使用slice时一样来获取传给函数的参数们;

有一点值得注意,golang的不定参数不需要强制绑定参数的出现。

举个例子,我想在c语言中实现一个求和任意个整数的函数sum:

int sum(int num, ...) {
    // todo
}

我们只有先指定至少一个非不定参数的形参(num)才能使用...不定参数,在golang中是不需要这样做的:

func sum(nums ...int) int {
    //todo
}

这也是golang语法简洁的其中一个体现。

传递参数给...不定参数

传递参数给带有不定参数的函数有两种形式,第一种与通常的参数传递没有什么区别,拿上一节的sum举个例子:

sum(1, 2, 3)
sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

除了参数的个数是动态变化的之外和普通的函数调用是一致的。

第二种形式是使用...运算符以变量...的形式进行参数传递,这里的变量必须是与不定参数类型相同的slice,而不能是其他类型(没错,数组也不可以),看个例子:

numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
sum(numbers...) // 和sum(1, 2, 3, 4, 5, 6, 7, 8, 9. 10)等价

这种形式最常用的地方是在内置函数append里:

result := []int{1, 3}
data := []int{5, 7, 9}
result = append(result, data...) // result == []int{1, 3, 5, 7, 9}

是不是和python的解包操作很像,没错,大部分情况下你可以把...运算符当做是golang的unpack操作,不过有几点不同还是要注意的:

第一,只能对slice类型使用...运算符:

arr := [...]int{1, 2, 3, 4, 5}
sum(arr...) // 编译无法通过

你会见到这样的报错信息:cannot use arr (type [5]int) as type []int in argument to sum

这是因为不定参数实际是个slice,...运算符是个语法糖,它把前面的slice直接复制给不定参数,而不是先解包成独立的n个参数再传递,这也是为什么我只说...运算符看起来像unpack的原因。

第二个需要注意的地方是不能把独立传参和...运算符混用,再看个例子:

slice := []int{2, 3, 4, 5}
sum(1, slice...) // 无法通过编译

这次你会见到一个比较长的报错:

too many arguments in call to sum
    have (number, []int...)
    want (...int)

这是和前面所说的原因是一样的,...运算符将不定参数直接替换成了slice,这样就导致前一个独立给出的参数不再算入不定参数的范围内,使得函数的参数列表从(...int)变成了(int, ...int),最终使得函数类型不匹配编译失败。

正确的做法也很简单,不要混合使用...运算符给不定参数传参即可。

读了这篇文章,再加上一些简单的联系,我相信你们一定也能掌握golang不定参数的使用。

参考:

https://golang.org/ref/spec#Passing_arguments_to_..._parameters

https://golang.org/doc/effective_go.html#append

原文地址:https://www.cnblogs.com/apocelipes/p/9861315.html

时间: 2024-08-05 20:25:41

了解golang的不定参数(... parameters),这一篇就够了的相关文章

Golang的不定参数

在很多语言中都提供了不定参数和函数重载以及函数式语言中得闭包来提高函数的灵活性.如果使用过fmt包里的函数,那么你就已经接触到了Golang的不定参数了.那么如何定义一个自己的不定参数的函数呢? 一.函数定义 首先来看如何定义一个不定参数的函数: func YourFun(v... interface{}){ } 该函数定义,定义了一个接受任何数目任何类型参数的函数.这里特殊的语法是三个点"...",在一个变量后面加上三个点后,表示从该处开始接受不定参数,不同于python,golan

golang中不定参数与数组切片的区别

package main import "fmt" func main() { myfunc1(88, 42, 12, 56) //传递不定数量的参数 myfunc2([]int{88, 42, 12, 56}) //传递一个数组切片 } func myfunc1(args ...int) { //接受不定数量的参数,这些参数的类型全部是int for _, arg := range args { fmt.Println(arg) } } func myfunc2(args []int

java的不定参数,可变参数Object ...

对于java中不定参数,或者是可变参数Object ... 这是JDK1.5的新特性 针对不定参数的其他问题,可以参考Java不定长度参数[http://blog.chinaunix.net/uid-200142-id-3124427.html]

不定参数的应用

不定参数当年做为C/C++语言一个特长被很多人推崇,但是实际上这种技术并没有应用很多.除了格式化输出之外,我实在没看到多少应用.主要原因是这种技术比较麻烦,副作用也比较多,而一般情况下重载函数也足以替换它.尽管如此,既然大家对它比较感兴趣,我就简单总结一下它的使用和需要注意的常见问题.原理:刚学C语言的时候,一般人都会首先接触printf函数.通过这个函数,你可以打印不定个数的变量到屏幕,如:printf("%d", 3);printf("%d,%d",3,4);

[Python进阶]001.不定参数

不定参数 介绍 元组参数 字典参数 混合 介绍 不定参数用 * 和 ** 定义 不定参数必须在其他所有参数之后 例子:os.path.join 方法就可以写入不定数量的参数 元组参数 定义:*args 以*作为参数前缀 会将传入的多个参数作为一个元组传入 代码 def fun(*args): for i in args: print i fun('a', 'b', 'c', 'd') def fun2(arg1, arg2, *args): # 带2个固定参数 print 'arg1:', ar

JDK5不定参数方法

jdk5之后出现了调用方法时传递不定参数的情况,如下所示: List<Intrger> list1 = Arrays.asList(new Integer[]{1,2,3}); List<int[]> list2 = Arrays.asList(new int[]{1,2,3}); 在使用不定参数时,可以传入一个数组或是以逗号间隔的参数列表.但是以上两行代码都向方法中传入数组,而传入基本类型数组时并没有按照预想的返回List<Intrger>,而是返回List<i

iOS 不定参数方法,类似UIAlertView的方法

//-------------------------- 方法申明 -------------------------- /** *  模仿UIAlertView方法 * *  @param argument 不定参数个数 */ - (void)copyAlertViewMethod:(id)argument, ... NS_REQUIRES_NIL_TERMINATION;//加了NS_REQUIRES_NIL_TERMINATION自动补齐功能就会自动在后面加nil //----------

JavaScript中使用arguments来实现不定参数的计算

在JavaScript中可以使用arguments对象来实现不定参数 例如:不定参数的相加实现 add(1,2)      ==>3 add(1,2,3)   ==>6 var add = function(){ var total = 0; for(var index = 0;index < arguments.length; index++){ total = total + arguments[index]; } return total; } alert("1加2的值是

C和C++中的不定参数

在初学C的时候,我们都会用到printf函数来写Hello World的程序.在我们看printf函数的声明时,会看到类似于下面代码 int printf(const char * __restrict, ...); 另外,在我们学习C和C++的时候,函数的声明总是确定个数和类型的,而我们在用printf的时候,却可以一次输出多个参数. 这就是我们要提的不定参数了. 在32位的C和C++编程中,函数调用是有规约的,并且各个编译器也基本达成了一致,尽管他们编译出的东西基本不能通用.关于调用规约的东