go实例—函数或方法的可变长参数

支持可变长参数列表的函数可以支持任意个传入参数,比如fmt.Println函数就是一个支持可变长参数列表的函数。

需要注意的是,可变长参数应该是函数定义的最右边的参数,即最后一个参数

package main
import "fmt"
// 这个函数可以传入任意数量的整型参数
func sum(nums ...int) {
	fmt.Println(nums)
	total := 0
	for i, num := range nums {
		fmt.Println(i)
		total += num
	}
	fmt.Println(total)
}
func main() {
	// 支持可变长参数的函数调用方法和普通函数一样
	// 也支持只有一个参数的情况
	sum(1)
	sum(1, 2)
	sum(1, 2, 3)
	// 如果你需要传入的参数在一个切片中,像下面一样
	// "func(slice...)"把切片打散传入
	nums := []int{1, 2, 3, 4}
	sum(nums...)
}

  输出结果:

[1]
0
1
[1 2]
0
1
3
[1 2 3]
0
1
2
6
[1 2 3 4]
0
1
2
3
10

 =============== 坑 =====================

package main
import(
	"fmt"
)
func TestArgs(first int,arg ...interface{}){
	fmt.Println(first,arg)
}

func main(){
	nums:=[]int64{1,2,3,4}
	TestArgs(1,nums...)
}

想要实现的代码逻辑很明了

1. TestArgs 接受一个 int 参数,可变长的参数,并且类型为 interface{}

2. nums 做为 slice,使用 ... 语法打散后传入 TestArgs

看上去逻辑没问题,但编译报错

[root@YY yang]# go build tt.go
# command-line-arguments
./tt.go:13:11: cannot use nums (type []int64) as type []interface {} in argument to TestArgs

居然报类型不匹配,写 Go 也一年了,这块的认知太不到位,一直认为会将 nums 打散,再以 interface{} 这个通用类型组成 interface{} slice 传到 TestArgs

那么,我们看看到底 nums 传进去后是什么

package main

import (
	"fmt"
	"reflect"
)

func TestArgs(first int, arg ...interface{}) {
	fmt.Println(first, reflect.TypeOf(arg))
}

func main() {
	nums := []interface{}{1, 2, 3, 4}
	TestArgs(1, nums...)
}

  执行结果

[root@YY yang]# ./tt
1 []interface {}

  那么确认是把可变参数当做 slice 传给函数,这点和 python 很像。那我们再看看 slice 是不是同一个

package main

import (
	"fmt"
	"reflect"
)

func TestArgs(first int, arg ...interface{}) {
	fmt.Println(first, reflect.TypeOf(arg))
	fmt.Printf("TestArgs addr of slice %p\n", arg)
	fmt.Println(arg)
}

func main() {
	nums := []interface{}{1, 2, 3, 4}
	fmt.Printf("TestArgs addr of slice %p\n", nums)
	TestArgs(1, nums...)
	TestArgs(2, "abc", "def", "ghlfk")
}

  执行后输出如下

[root@YY yang]# ./tt
TestArgs addr of slice 0xc42004a040
1 []interface {}
TestArgs addr of slice 0xc42004a040
[1 2 3 4]
2 []interface {}
TestArgs addr of slice 0xc420058150
[abc def ghlfk]

  nums和arg地址相同!原来,如果传入的可变参数本身就是由 slice 以 ... 形式传入的,那么就直接使用这个 slice,不会新建 slice。那么我理解的 Go 的可变参数执行方式:

对于 func(first int, arg ...T)

1. 当不传可变参数时,对应的 arg 就是 nil
2. 传入单个可变参数时,实际上执行 [] T{arg1,arg2,arg3}
3. 传入...语法的 slice时,直接使用这个 slice

由此我们就很好理解开篇的小例子为什么执行不了,[]int64 和 []interface{} 是两个类型的 slice 。

  转自:https://www.jianshu.com/p/94710d8ab691

转载于:https://www.cnblogs.com/yorkyang/p/8144434.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值