多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
接连两篇函数专题深度解析,相信大家已经对函数的语法有了深入的了解。 > go语言github项目:https://github.com/minibear2333/how_to_code [TOC] 这次小熊给大家带来了一个函数的特性【可变参数】,作为函数专题的结束。 ### 有没有发现? 我们有时候会用到的输出、错误输出、字符串格式化系统函数,你可以传入任意个数的参数,他全都能处理! ```go fmt.Println("a","b","c","d") ``` 就像一个任劳任怨的老父亲,那到底是为什么呢? ### 因为 因为在`go`语言中语言级别自带了一种语法,可以声明可变参数! ```go func 函数名(固定参数,v ...T) (返回参数列表){ 函数体 } ``` ### 怎么用? 先和小熊一起试试,写一个不定参数累加的函数 ```go func sum(t ...int) (res int) { for _, v := range t { res += v } return res } fmt.Println(sum(1, 2, 3, 4, 5)) ``` 输出结果 ``` 15 ``` ### 如果连参数类型都不知道,怎么办? 上一节我们已知参数类型是`int`,还记得我们前面说过的`switch`判断类型做处理的例子吗?[switch和type switch](https://mp.weixin.qq.com/s/cQzuPC2MwDBvzfWnWFhDJg)。 参考这个例子重写下函数,让他可以接收任意类型的参数。 ```go func sumNum(t ...interface{}) (res float64){ for _,tmp := range t{ switch v :=tmp.(type) { case int: res += float64(v) case float64: res+= v case float32: res += float64(v) } } return res } ``` 测试下 ```go fmt.Println(sumNum(1,2.1,"asd",true)) ``` 因为忽略了输出 ``` 3.1 ``` 但是上面的例子并没有覆盖全部的数字,如果一个一个类型的匹配会疯掉的。有没有更好的方法,可以一下子匹配到所有的数字? ```go func sumNum(t ...interface{}) (res float64) { for _, tmp := range t { switch v := tmp.(type) { case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, complex64, complex128: convertStr := fmt.Sprintf("%v", v) convertFloat64, _ := strconv.ParseFloat(convertStr, 64) res += convertFloat64 } } return res } ``` 上面的代码在case里一下子匹配了所有可能的数字类型,再用格式化输出转换成字符串,最后转换成`float64`来使用,这是一种折中的办法,速度可能会比较慢(因为格式化内部逻辑比较复杂消耗速度)。 为了保证速度还是不要省掉一大堆的`case`,明确了类型再做强转。 ### 留给你的寻找的答案 有没有一种只留一个`case`,同时处理速度又快的方法呢? —— 爱你们的小熊