了解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(, , )
sum(, , , , , , , , , )
除了参数的个数是动态变化的之外和普通的函数调用是一致的。
第二种形式是使用...运算符以变量...的形式进行参数传递,这里的变量必须是与可变参数类型相同的slice,而不能是其他类型(没错,数组也不可以),看个例子:
numbers := []int{, , , , , , , , , }
sum(numbers...) // 和sum(1, 2, 3, 4, 5, 6, 7, 8, 9. 10)等价
这种形式最常用的地方是在内置函数append里:
result := []int{, }
data := []int{, , }
result = append(result, data...) // result == []int{1, 3, 5, 7, 9}
是不是和python的解包操作很像,没错,大部分情况下你可以把...运算符当做是golang的unpack操作,不过有几点不同还是要注意的:
第一,只能对slice类型使用...运算符:
arr := [...]int{, , , , }
sum(arr...) // 编译无法通过
你会见到这样的报错信息:cannot use arr (type [5]int) as type []int in argument to sum
这是因为可变参数实际是个slice,...运算符是个语法糖,它把前面的slice直接复制给可变参数,而不是先解包成独立的n个参数再传递,这也是为什么我只说...运算符看起来像unpack的原因。
第二个需要注意的地方是不能把独立传参和...运算符混用,再看个例子:
slice := []int{, , , }
sum(, 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
了解golang的可变参数(... parameters),这一篇就够了的更多相关文章
- golang 中可变参数的个数
package main import "fmt" func Greeting(prefix string, who ... string) { fmt.Println(prefi ...
- 坑爹的 Java 可变参数,把我整得够惨。。
最近在写一个功能点,用了 Java 中的可变参数,真是把我搞得够惨.. 什么是可变参数? 就是方法参数用 Object... args 三个点形式,一个参数可以接收多个参数. 实际的代码就不帖了,来看 ...
- 【GoLang】golang 中可变参数的 定义、传递 示例
支持可变长参数列表的函数可以支持任意个传入参数,比如fmt.Println函数就是一个支持可变长参数列表的函数. package main import "fmt" // 这个函数 ...
- SpringMVC参数绑定,这篇就够了!
SpringMVC参数绑定,简单来说就是将客户端请求的key/value数据绑定到controller方法的形参上,然后就可以在controller中使用该参数了 下面通过5个常用的注解演示下如何进行 ...
- params可变参数、SqlCommand.Parameters.add()方法
namespace params可变参数{ class Program { static void Main(string[] args) { int[] num = {66,99,55,44, }; ...
- Python星号*与**用法分析 What does ** (double star/asterisk) and * (star/asterisk) do for parameters? 必选参数 默认参数 可变参数 关键字参数
python中*号**的区别 - CSDN博客 https://blog.csdn.net/qq_26815677/article/details/78091452 定义可变参数和定义 list 或 ...
- golang中函数的可变参数
package main import "fmt" // 一个函数中最多只可有一个可变参数, 如果参数列表中还有其它类型的参数,则可变参数写在最后 // 注意:参数不定,参数的个数 ...
- 【转载】va_list 可变参数 简介 va_copy vprintf
[说明]本文转载自 smart 的文章 http://blog.sina.com.cn/s/blog_590be5290100qhxr.html 及百度百科 va_list是一个宏,由va_star ...
- 可变参数列表-Java SE5新特性(转)
Java1.5增加了新特性:可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理.注意:可变参数必须位于最后一项.当可变参数个数多于一个时,必将有一个不是最后一项,所以只支持 ...
随机推荐
- SJCP认证题前五十题填坑
在做Java的SJCP认证试题时自己整理了一些Java基础细节知识点,以下是知识点陈列 1.标签机制:标签起作用的唯一的地方刚好在迭代语句之前(不然编译错误) continue label1 直接转到 ...
- enumerate的用法
names = ["tony","huluwa","tom","jerry","lala"]for ...
- <笔记>字体文件的路径问题
如果做过虚拟域名,不可以通过127.0.0.1来访问字体文件 改成通过虚拟域名访问,就没问题: 不过更建议使用相对路径
- Windows平台最方便最易用的法语输入法
原文:http://wenwen.sogou.com/z/q1700007921.htm 对于XP,在“控制面板”中选择“输入法区域设置”,单击“更改”,出现一个“设置”框:选择“添加”,然后选择“法 ...
- vue computed计算属性和watch监听属性解疑答惑
computed计算属性 计算属性类似于方法,用于输出data中定义的属性数据的结果,data数据变化时,计算属性的结果会同步变化,需要注意的是计算属性不可与data定义的属性同名. 相比于方 ...
- MyBatis的好处及常见问题
好处 MyBatis持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动.创建connection.创建statement.手动设置 ...
- 微信小程序中如何使用WebSocket实现长连接(含完整源码)
本文由腾讯云技术团队原创,感谢作者的分享. 1.前言 微信小程序提供了一套在微信上运行小程序的解决方案,有比较完整的框架.组件以及 API,在这个平台上面的想象空间很大.腾讯云研究了一番之后,发现 ...
- Android开发之如何避免ANR(Keeping Your App Responsive)
一:什么是ANR 如果应用程序不能响应用户的输入了,那么就可以说应用ANR了. 如果需要运行一个耗时较长的操作的时候,不要把这个任务放在UI线程上运行,而是单独创建一个线程运行那些操作. 以下情况会出 ...
- .net core 发布linux报错“The configured user limit (128) on the number of inotify instances has been reached”
https://stackoverflow.com/questions/45875981/error-while-reading-json-file-in-dotnet-core-the-config ...
- Java 虚拟机的内存溢出
在Java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生 OutOfMemoryError 异常的可能. 在Eclipse中进行JVM参数设置 可以直接通过上方菜单栏的 ...