最近在看redis的代码 这段代码能传递多个参数 而定义上却很简洁
sds sdscatprintf(sds s, const char *fmt, ...) {
va_list ap;
char *t;
va_start(ap, fmt);
t = sdscatvprintf(s,fmt,ap);
va_end(ap);
return t;
}
查了一下这是c++可变参数函数 心想go语言如何实现可变参数呢 便浅浅的学习了一下
当然这段代码和原先代码功能不一样
func sdscatprintf(s string, fmtStr string, args ...interface{}) string {
result := fmt.Sprintf(fmtStr, args...)
return s + result
}
目录
一.可变参数函数的基本格式
func functionName(变量名 变量类型, param2 type2,args ...typeN) returnType {
}
-
在函数中,将最后一个参数的类型指定为
...
加上变参的类型。 -
我们可以使用 args 来访问传入的可变参数。args是一个切片类型(
[]typeN
),其中包含所有传入的可变参数。 -
因为args是切片,所以我们可以像用切片一样使用循环处理每个参数。
-
可以将其他参数与可变参数一起使用,按照定义的顺序传递参数。
二.可变参数函数的简单使用
举个经典例子
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
在这个例子中,nums
参数表示这是一个类型为int
的可变参数函数....,也就是说你可以给这个函数传递任意数量的int
类型参数。(当然interface就是任意类型)
fmt.Println(sum(1, 2))
fmt.Println(sum(1, 2, 3))
结果显而易见 2 6
三.可变参数函数的传递
func sdscatprintf(s string, fmtStr string, args ...interface{}) string {
result := fmt.Sprintf(fmtStr, args...)
return s + result
}
就像刚刚这段代码 这个例子里面args是一个interface{}
类型的切片,而args...
则将这个切片展开,变成一组interface参数进行传递。
s := "Hello"
result := sdscatprintf(s, " %s, %s!", "Gopher", "Welcome")
fmt.Println(result)
输出: Hello Gopher, Welcome!
四.其他
sds sdscatprintf(sds s, const char *fmt, ...) {
va_list ap;
char *t;
va_start(ap, fmt);
t = sdscatvprintf(s,fmt,ap);
va_end(ap);
return t;
}
再说一下 这段c++代码里面va_list吧
它是C语言中处理可变参数的宏
查看定义可以知道
是char* 类型那么就很好理解
va_start就是开始对可变参数列表ap
的访问,并让它指向第一个参数fmt
后面的位置,即真正的可变参数的起始位置。
va_end则是访问完毕后,需要调用va_end
以完成可变参数列表的处理。