本文共 1043 字,大约阅读时间需要 3 分钟。
Golang的可变参实现跟C/C++的不太一样,编译器把可变参解析成了一个切片结构传给了函数,充分利用了Go内置的数据结构。而C/C++的实现则要结合x86平台调用约定和ABI手册了,可以看:。
一个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.gofunc 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*可以接受任何类型的指针。
转载地址:http://ebqli.baihongyu.com/