package main

import (
	"fmt"
	"os"
)

// 可变参数
// 在声明可变参数函数时，需要在参数列表的最后一个参数类型之前加上省略符号“...”，
// 这表示该函数会接收任意数量的该类型参数。
func sum(vals ...int) int {
	total := 0
	for _, val := range vals {
		total += val
	}
	return total
}
func main() {
	fmt.Println(sum())           // "0"
	fmt.Println(sum(3))          // "3"
	fmt.Println(sum(1, 2, 3, 4)) // "10"

	// 虽然在可变参数函数内部，...int 型参数的行为看起来很像切片类型，
	// 但实际上，可变参数函数和以切片作为参数的函数是不同的。
	var f = func(a ...int) {
		fmt.Printf("%T\n", a)
	}
	var g = func(a []int) {
		fmt.Printf("%T\n", a)
	}
	fmt.Printf("%T\n", f) // "func(...int)"
	fmt.Printf("%T\n", g) // "func([]int)"

	// 但是可变参数函数内部，实际传入的参数还是一个切片
	f(1, 2, 3)
	g([]int{1, 2, 3})

	// 可变参数函数经常被用于格式化字符串。
	// 下面的errorf函数构造了一个以行号开头的，
	// 经过格式化的错误信息。函数名的后缀f是一种通用的命名规范，
	// 代表该可变参数函数可以接收Printf风格的格式化字符串。
	errorf := func(linenum int, format string, args ...interface{}) {
		fmt.Fprintf(os.Stderr, "Line %d: ", linenum)
		fmt.Fprintf(os.Stderr, format, args...)
		fmt.Fprintln(os.Stderr)
	}
	linenum, name := 12, "count"
	errorf(linenum, "undefined: %s", name) // "Line 12: undefined: count"

}
