Go语言模型:可变参函数的实现机制

Golang的可变参实现跟C/C++的不太一样,编译器把可变参解析成了一个切片结构传给了函数,充分利用了Go内置的数据结构。而C/C++的实现则要结合x86平台调用约定和ABI手册了,可以看:Linux C variadic可变参数:va_list 在x86和x64下的区别与实现原理
一个Go的简单例子:

func sum2(vals []int) int {
	total := 0
	for _, v := range vals {
		total += v
	}
	return total
}

func sum(vals ...int) (int, int) {
	total := 0
	fmt.Println(reflect.TypeOf(vals)) // []int
	for _, val := range vals {
		total += val
	}
	return total, sum2(vals)
}

func main() {
	re, re2 := sum(1, 2, 3)
	fmt.Println(re, re2)              // 6 6
	fmt.Println(reflect.TypeOf(sum))  // func(...int) (int, int)
	fmt.Println(reflect.TypeOf(sum2)) // func([]int) int
}

通过上面例子可以看出,虽然实现上Go编译器把可变参解析成了一个切片,但是函数的type还是不一样的,TypeOf也看了出来。

知道这个机制,那么最常用的格式化打印函数就很容易猜到实现原理了,可变参传递通过一个空接口类型的切片即可,然后通过parse格式化的fmt字符串一个一个对应解析出切片内元素的类型,转换成字符串输出即可。

// @file: io.go
func Printf(format string, a ...interface{}) (n int, err error) {
	return Fprintf(os.Stdout, format, a...) // 调用 p.doPrintf(format, a)
}

func (p *pp) doPrintf(format string, a []interface{}) 

上面的interface{}某种程度上弥补了Go泛型能力的缺失,任何类型都实现了空接口。这也有点类似Java的Object类是所有类的祖先,也有点像C的void*可以接受任何类型的指针。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值