接连两篇函数专题深度解析,相信大家已经对函数的语法有了深入的了解。
> 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`,同时处理速度又快的方法呢?
—— 爱你们的小熊
- 安装与下载
- 投稿大纲
- 第一章、跑起来
- 为什么要学 go 语言?
- 让你的 Golang 项目在 IDE 里跑起来
- 第一个 go 程序
- go mod最佳实践
- 第二章、语言基础
- 声明【变量】的各种方式
- 常量+各种类型转换
- switch和type switch
- 循环语句的多种形式、死循环、break/continue
- range深度解析
- 第三章、函数和容器
- 函数简单使用和基本知识解析
- 匿名函数和闭包
- 可变参数
- 集合(map)
- 数组和切片
- 切片知识补充
- 第四章、指针、结构体、接口和异常处理
- 指针讨论
- 结构体
- 接口与多态
- 异常处理
- 第五章、再学一点运用自如
- 其他常用操作
- Go文件操作大全
- Go代码基本标准规范
- 切片排序sort包的使用
- Golang打镜像Dockerfile的写法
- 等待goroutine完成任务,循环中使用goroutine
- kinping.flag包读取命令行配置