/* 03-variadic-functions.go - Go 语言可变参数函数详解 学习目标: 1. 掌握可变参数函数的语法 2. 理解可变参数的传递机制 3. 学会可变参数的实际应用 4. 了解可变参数的限制和注意事项 5. 掌握可变参数的最佳实践 知识点: - 可变参数语法 (...type) - 可变参数的传递和展开 - 空参数和单参数处理 - 可变参数与切片的关系 - 可变参数的类型限制 - 实际应用场景 */ package main import ( "fmt" "strings" ) func main() { fmt.Println("=== Go 语言可变参数函数详解 ===\n") // 演示基本可变参数函数 demonstrateBasicVariadicFunctions() // 演示可变参数的传递 demonstrateVariadicParameterPassing() // 演示可变参数与其他参数的组合 demonstrateVariadicWithOtherParams() // 演示可变参数的类型处理 demonstrateVariadicTypeHandling() // 演示可变参数的实际应用 demonstratePracticalApplications() // 演示可变参数的高级用法 demonstrateAdvancedVariadicUsage() // 演示可变参数的限制和注意事项 demonstrateVariadicLimitations() } // demonstrateBasicVariadicFunctions 演示基本可变参数函数 func demonstrateBasicVariadicFunctions() { fmt.Println("1. 基本可变参数函数:") // 数字求和 fmt.Printf(" 数字求和:\n") fmt.Printf(" sum() = %d\n", sum()) fmt.Printf(" sum(1) = %d\n", sum(1)) fmt.Printf(" sum(1, 2, 3) = %d\n", sum(1, 2, 3)) fmt.Printf(" sum(1, 2, 3, 4, 5) = %d\n", sum(1, 2, 3, 4, 5)) // 字符串连接 fmt.Printf(" 字符串连接:\n") fmt.Printf(" concat() = \"%s\"\n", concat()) fmt.Printf(" concat(\"Hello\") = \"%s\"\n", concat("Hello")) fmt.Printf(" concat(\"Hello\", \" \", \"World\") = \"%s\"\n", concat("Hello", " ", "World")) fmt.Printf(" concat(\"Go\", \" is\", \" awesome\", \"!\") = \"%s\"\n", concat("Go", " is", " awesome", "!")) // 找最大值 fmt.Printf(" 找最大值:\n") fmt.Printf(" max(1) = %d\n", max(1)) fmt.Printf(" max(3, 1, 4, 1, 5) = %d\n", max(3, 1, 4, 1, 5)) fmt.Printf(" max(10, 5, 8, 3, 9, 2, 7) = %d\n", max(10, 5, 8, 3, 9, 2, 7)) fmt.Println() } // demonstrateVariadicParameterPassing 演示可变参数的传递 func demonstrateVariadicParameterPassing() { fmt.Println("2. 可变参数的传递:") // 直接传递多个参数 fmt.Printf(" 直接传递多个参数:\n") result1 := multiply(2, 3, 4, 5) fmt.Printf(" multiply(2, 3, 4, 5) = %d\n", result1) // 传递切片(需要展开) fmt.Printf(" 传递切片(使用 ... 展开):\n") numbers := []int{2, 3, 4, 5} result2 := multiply(numbers...) fmt.Printf(" numbers := %v\n", numbers) fmt.Printf(" multiply(numbers...) = %d\n", result2) // 混合传递 fmt.Printf(" 混合传递:\n") result3 := multiply(1, 2) moreNumbers := []int{3, 4, 5} result4 := multiply(append([]int{1, 2}, moreNumbers...)...) fmt.Printf(" multiply(1, 2) = %d\n", result3) fmt.Printf(" 混合传递结果 = %d\n", result4) // 空切片传递 fmt.Printf(" 空切片传递:\n") var emptySlice []int result5 := multiply(emptySlice...) fmt.Printf(" multiply(emptySlice...) = %d\n", result5) // 传递给其他可变参数函数 fmt.Printf(" 传递给其他可变参数函数:\n") numbers2 := []int{10, 20, 30} avg := average(numbers2...) fmt.Printf(" average(%v) = %.2f\n", numbers2, avg) fmt.Println() } // demonstrateVariadicWithOtherParams 演示可变参数与其他参数的组合 func demonstrateVariadicWithOtherParams() { fmt.Println("3. 可变参数与其他参数的组合:") // 固定参数 + 可变参数 fmt.Printf(" 固定参数 + 可变参数:\n") result1 := formatMessage("INFO", "User login", "successful", "from IP 192.168.1.1") fmt.Printf(" %s\n", result1) result2 := formatMessage("ERROR", "Database connection failed") fmt.Printf(" %s\n", result2) // 多个固定参数 + 可变参数 fmt.Printf(" 多个固定参数 + 可变参数:\n") result3 := calculateWithOperation("add", 1, 2, 3, 4, 5) fmt.Printf(" calculateWithOperation(\"add\", 1, 2, 3, 4, 5) = %.2f\n", result3) result4 := calculateWithOperation("multiply", 2, 3, 4) fmt.Printf(" calculateWithOperation(\"multiply\", 2, 3, 4) = %.2f\n", result4) result5 := calculateWithOperation("average", 10, 20, 30, 40, 50) fmt.Printf(" calculateWithOperation(\"average\", 10, 20, 30, 40, 50) = %.2f\n", result5) // 带默认值的可变参数函数 fmt.Printf(" 带默认值的可变参数函数:\n") config1 := createConfig("myapp") fmt.Printf(" createConfig(\"myapp\") = %+v\n", config1) config2 := createConfig("myapp", "debug=true", "port=8080", "timeout=30") fmt.Printf(" createConfig with options = %+v\n", config2) fmt.Println() } // demonstrateVariadicTypeHandling 演示可变参数的类型处理 func demonstrateVariadicTypeHandling() { fmt.Println("4. 可变参数的类型处理:") // 不同类型的可变参数 fmt.Printf(" 字符串可变参数:\n") joined := joinStrings(", ", "apple", "banana", "cherry", "date") fmt.Printf(" joinStrings(\", \", \"apple\", \"banana\", \"cherry\", \"date\") = \"%s\"\n", joined) // 接口类型的可变参数 fmt.Printf(" 接口类型的可变参数:\n") printValues("混合类型:", 42, "hello", 3.14, true, []int{1, 2, 3}) // 结构体类型的可变参数 fmt.Printf(" 结构体类型的可变参数:\n") person1 := Person{Name: "Alice", Age: 25} person2 := Person{Name: "Bob", Age: 30} person3 := Person{Name: "Charlie", Age: 35} avgAge := calculateAverageAge(person1, person2, person3) fmt.Printf(" 平均年龄: %.1f\n", avgAge) // 函数类型的可变参数 fmt.Printf(" 函数类型的可变参数:\n") add := func(a, b int) int { return a + b } multiply := func(a, b int) int { return a * b } subtract := func(a, b int) int { return a - b } results := applyOperations(10, 5, add, multiply, subtract) fmt.Printf(" applyOperations(10, 5, add, multiply, subtract) = %v\n", results) fmt.Println() } // demonstratePracticalApplications 演示可变参数的实际应用 func demonstratePracticalApplications() { fmt.Println("5. 可变参数的实际应用:") // 应用1: 日志记录 fmt.Printf(" 应用1 - 日志记录:\n") logInfo("用户登录", "用户ID", 123, "IP地址", "192.168.1.1") logError("数据库连接失败", "错误码", 1001, "重试次数", 3) logDebug("缓存命中", "键", "user:123", "值", "Alice") // 应用2: SQL 查询构建 fmt.Printf(" 应用2 - SQL 查询构建:\n") query1 := buildSelectQuery("users", "name", "email", "age") fmt.Printf(" %s\n", query1) query2 := buildSelectQuery("products", "id", "name", "price", "category", "stock") fmt.Printf(" %s\n", query2) // 应用3: HTTP 路由注册 fmt.Printf(" 应用3 - HTTP 路由注册:\n") registerRoute("GET", "/users", authMiddleware, loggingMiddleware, getUsersHandler) registerRoute("POST", "/users", authMiddleware, validateMiddleware, createUserHandler) // 应用4: 数据验证 fmt.Printf(" 应用4 - 数据验证:\n") userData := map[string]interface{}{ "name": "Alice", "email": "alice@example.com", "age": 25, } errors := validateData(userData, validateRequired("name"), validateEmail("email"), validateRange("age", 0, 150), ) if len(errors) == 0 { fmt.Printf(" 数据验证通过\n") } else { fmt.Printf(" 验证错误: %v\n", errors) } // 应用5: 配置合并 fmt.Printf(" 应用5 - 配置合并:\n") defaultConfig := Config{Port: 8080, Debug: false, Timeout: 30} userConfig := Config{Debug: true, MaxConnections: 100} envConfig := Config{Port: 9090, Timeout: 60} finalConfig := mergeConfigs(defaultConfig, userConfig, envConfig) fmt.Printf(" 最终配置: %+v\n", finalConfig) fmt.Println() } // demonstrateAdvancedVariadicUsage 演示可变参数的高级用法 func demonstrateAdvancedVariadicUsage() { fmt.Println("6. 可变参数的高级用法:") // 可变参数的递归处理 fmt.Printf(" 可变参数的递归处理:\n") result1 := recursiveSum(1, 2, 3, 4, 5) fmt.Printf(" recursiveSum(1, 2, 3, 4, 5) = %d\n", result1) // 可变参数的函数式处理 fmt.Printf(" 可变参数的函数式处理:\n") numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} evenSum := reduceInts(filterInts(numbers, isEven)...) fmt.Printf(" 偶数之和: %d\n", evenSum) oddProduct := reduceInts(filterInts(numbers, isOdd)...) fmt.Printf(" 奇数之和: %d\n", oddProduct) // 可变参数的管道处理 fmt.Printf(" 可变参数的管道处理:\n") pipeline := createPipeline( func(x int) int { return x * 2 }, // 乘以2 func(x int) int { return x + 1 }, // 加1 func(x int) int { return x * x }, // 平方 ) for i := 1; i <= 3; i++ { result := pipeline(i) fmt.Printf(" pipeline(%d) = %d\n", i, result) } // 可变参数的选项模式 fmt.Printf(" 可变参数的选项模式:\n") server1 := createServer("localhost", withPort(8080), withTimeout(30), withDebug(true), ) fmt.Printf(" 服务器1: %+v\n", server1) server2 := createServer("0.0.0.0", withPort(9090), withMaxConnections(1000), ) fmt.Printf(" 服务器2: %+v\n", server2) fmt.Println() } // demonstrateVariadicLimitations 演示可变参数的限制和注意事项 func demonstrateVariadicLimitations() { fmt.Println("7. 可变参数的限制和注意事项:") // 限制1: 可变参数必须是最后一个参数 fmt.Printf(" 限制1: 可变参数必须是最后一个参数\n") fmt.Printf(" ✓ func example(a int, b ...string) - 正确\n") fmt.Printf(" ✗ func example(a ...int, b string) - 错误\n") // 限制2: 一个函数只能有一个可变参数 fmt.Printf(" 限制2: 一个函数只能有一个可变参数\n") fmt.Printf(" ✗ func example(a ...int, b ...string) - 错误\n") // 注意事项1: 可变参数是切片 fmt.Printf(" 注意事项1: 可变参数在函数内部是切片\n") inspectVariadicParam(1, 2, 3, 4, 5) // 注意事项2: 修改可变参数会影响原始切片 fmt.Printf(" 注意事项2: 修改可变参数可能影响原始数据\n") originalSlice := []int{1, 2, 3, 4, 5} fmt.Printf(" 修改前: %v\n", originalSlice) modifyVariadicParam(originalSlice...) fmt.Printf(" 修改后: %v\n", originalSlice) // 注意事项3: 性能考虑 fmt.Printf(" 注意事项3: 性能考虑\n") fmt.Printf(" - 传递大量参数时,切片展开可能有性能开销\n") fmt.Printf(" - 考虑直接传递切片而不是可变参数\n") // 注意事项4: 类型安全 fmt.Printf(" 注意事项4: 类型安全\n") fmt.Printf(" - 可变参数必须是相同类型\n") fmt.Printf(" - 使用 interface{} 可以接受不同类型,但失去类型安全\n") // 最佳实践 fmt.Printf(" 最佳实践:\n") fmt.Printf(" 1. 优先考虑切片参数而不是可变参数\n") fmt.Printf(" 2. 可变参数适用于调用时参数数量不确定的场景\n") fmt.Printf(" 3. 注意可变参数的性能影响\n") fmt.Printf(" 4. 使用选项模式处理复杂的可选参数\n") fmt.Println() } // ========== 函数定义 ========== // 基本可变参数函数 func sum(numbers ...int) int { total := 0 for _, num := range numbers { total += num } return total } func concat(strings ...string) string { result := "" for _, str := range strings { result += str } return result } func max(numbers ...int) int { if len(numbers) == 0 { return 0 } maximum := numbers[0] for _, num := range numbers { if num > maximum { maximum = num } } return maximum } func multiply(numbers ...int) int { if len(numbers) == 0 { return 0 } result := 1 for _, num := range numbers { result *= num } return result } func average(numbers ...int) float64 { if len(numbers) == 0 { return 0 } total := sum(numbers...) return float64(total) / float64(len(numbers)) } // 固定参数 + 可变参数 func formatMessage(level string, messages ...string) string { timestamp := "2024-01-01 12:00:00" allMessages := strings.Join(messages, " ") return fmt.Sprintf("[%s] %s: %s", timestamp, level, allMessages) } func calculateWithOperation(operation string, numbers ...int) float64 { if len(numbers) == 0 { return 0 } switch operation { case "add": return float64(sum(numbers...)) case "multiply": return float64(multiply(numbers...)) case "average": return average(numbers...) default: return 0 } } type AppConfig struct { Name string Options map[string]string } func createConfig(name string, options ...string) AppConfig { config := AppConfig{ Name: name, Options: make(map[string]string), } for _, option := range options { parts := strings.SplitN(option, "=", 2) if len(parts) == 2 { config.Options[parts[0]] = parts[1] } } return config } // 类型处理函数 func joinStrings(separator string, strings ...string) string { return strings.Join(strings, separator) } func printValues(prefix string, values ...interface{}) { fmt.Printf(" %s ", prefix) for i, value := range values { if i > 0 { fmt.Printf(", ") } fmt.Printf("%v", value) } fmt.Printf("\n") } type Person struct { Name string Age int } func calculateAverageAge(people ...Person) float64 { if len(people) == 0 { return 0 } totalAge := 0 for _, person := range people { totalAge += person.Age } return float64(totalAge) / float64(len(people)) } func applyOperations(a, b int, operations ...func(int, int) int) []int { results := make([]int, len(operations)) for i, op := range operations { results[i] = op(a, b) } return results } // 实际应用函数 func logInfo(message string, keyValues ...interface{}) { fmt.Printf(" [INFO] %s", message) for i := 0; i < len(keyValues); i += 2 { if i+1 < len(keyValues) { fmt.Printf(" %v=%v", keyValues[i], keyValues[i+1]) } } fmt.Printf("\n") } func logError(message string, keyValues ...interface{}) { fmt.Printf(" [ERROR] %s", message) for i := 0; i < len(keyValues); i += 2 { if i+1 < len(keyValues) { fmt.Printf(" %v=%v", keyValues[i], keyValues[i+1]) } } fmt.Printf("\n") } func logDebug(message string, keyValues ...interface{}) { fmt.Printf(" [DEBUG] %s", message) for i := 0; i < len(keyValues); i += 2 { if i+1 < len(keyValues) { fmt.Printf(" %v=%v", keyValues[i], keyValues[i+1]) } } fmt.Printf("\n") } func buildSelectQuery(table string, columns ...string) string { if len(columns) == 0 { return fmt.Sprintf("SELECT * FROM %s", table) } return fmt.Sprintf("SELECT %s FROM %s", strings.Join(columns, ", "), table) } // 模拟中间件和处理器 func authMiddleware() { fmt.Printf(" - 认证中间件\n") } func loggingMiddleware() { fmt.Printf(" - 日志中间件\n") } func validateMiddleware() { fmt.Printf(" - 验证中间件\n") } func getUsersHandler() { fmt.Printf(" - 获取用户处理器\n") } func createUserHandler() { fmt.Printf(" - 创建用户处理器\n") } func registerRoute(method, path string, handlers ...func()) { fmt.Printf(" 注册路由: %s %s\n", method, path) for _, handler := range handlers { handler() } } // 验证函数类型 type ValidationFunc func(map[string]interface{}) []string func validateRequired(field string) ValidationFunc { return func(data map[string]interface{}) []string { if _, exists := data[field]; !exists { return []string{fmt.Sprintf("字段 %s 是必需的", field)} } return nil } } func validateEmail(field string) ValidationFunc { return func(data map[string]interface{}) []string { if email, ok := data[field].(string); ok { if !strings.Contains(email, "@") { return []string{fmt.Sprintf("字段 %s 不是有效的邮箱", field)} } } return nil } } func validateRange(field string, min, max int) ValidationFunc { return func(data map[string]interface{}) []string { if value, ok := data[field].(int); ok { if value < min || value > max { return []string{fmt.Sprintf("字段 %s 必须在 %d-%d 范围内", field, min, max)} } } return nil } } func validateData(data map[string]interface{}, validators ...ValidationFunc) []string { var allErrors []string for _, validator := range validators { if errors := validator(data); errors != nil { allErrors = append(allErrors, errors...) } } return allErrors } // 配置合并 type Config struct { Port int Debug bool Timeout int MaxConnections int } func mergeConfigs(configs ...Config) Config { result := Config{} for _, config := range configs { if config.Port != 0 { result.Port = config.Port } if config.Debug { result.Debug = config.Debug } if config.Timeout != 0 { result.Timeout = config.Timeout } if config.MaxConnections != 0 { result.MaxConnections = config.MaxConnections } } return result } // 高级用法函数 func recursiveSum(numbers ...int) int { if len(numbers) == 0 { return 0 } if len(numbers) == 1 { return numbers[0] } return numbers[0] + recursiveSum(numbers[1:]...) } func filterInts(numbers []int, predicate func(int) bool) []int { var result []int for _, num := range numbers { if predicate(num) { result = append(result, num) } } return result } func reduceInts(numbers ...int) int { return sum(numbers...) } func isEven(n int) bool { return n%2 == 0 } func isOdd(n int) bool { return n%2 == 1 } func createPipeline(functions ...func(int) int) func(int) int { return func(input int) int { result := input for _, fn := range functions { result = fn(result) } return result } } // 选项模式 type Server struct { Host string Port int Timeout int Debug bool MaxConnections int } type ServerOption func(*Server) func withPort(port int) ServerOption { return func(s *Server) { s.Port = port } } func withTimeout(timeout int) ServerOption { return func(s *Server) { s.Timeout = timeout } } func withDebug(debug bool) ServerOption { return func(s *Server) { s.Debug = debug } } func withMaxConnections(max int) ServerOption { return func(s *Server) { s.MaxConnections = max } } func createServer(host string, options ...ServerOption) Server { server := Server{ Host: host, Port: 80, Timeout: 10, Debug: false, } for _, option := range options { option(&server) } return server } // 限制和注意事项函数 func inspectVariadicParam(numbers ...int) { fmt.Printf(" 可变参数类型: %T\n", numbers) fmt.Printf(" 可变参数长度: %d\n", len(numbers)) fmt.Printf(" 可变参数容量: %d\n", cap(numbers)) fmt.Printf(" 可变参数值: %v\n", numbers) } func modifyVariadicParam(numbers ...int) { if len(numbers) > 0 { numbers[0] = 999 // 修改第一个元素 } } /* 运行这个程序: go run 03-variadic-functions.go 学习要点: 1. 可变参数使用 ...type 语法,必须是函数的最后一个参数 2. 可变参数在函数内部是切片类型 3. 传递切片给可变参数函数需要使用 ... 展开操作符 4. 一个函数只能有一个可变参数 5. 可变参数提供了灵活的函数调用方式 可变参数的语法: - 定义: func name(params ...type) { ... } - 调用: name(arg1, arg2, arg3) 或 name(slice...) - 内部: params 是 []type 类型的切片 常见应用场景: 1. 数学运算函数(求和、求积等) 2. 字符串处理函数 3. 日志记录函数 4. 配置和选项处理 5. 中间件和处理器链 6. 数据验证 7. SQL 查询构建 最佳实践: 1. 优先考虑切片参数,可变参数适用于调用便利性 2. 使用选项模式处理复杂的可选参数 3. 注意可变参数的性能影响 4. 保持函数签名的简洁性 5. 合理使用接口类型的可变参数 限制和注意事项: 1. 可变参数必须是最后一个参数 2. 一个函数只能有一个可变参数 3. 可变参数是切片,修改会影响原始数据 4. 大量参数时考虑性能影响 5. 类型必须相同(除非使用 interface{}) 高级用法: 1. 函数式编程风格 2. 选项模式 3. 中间件模式 4. 管道处理 5. 递归处理 6. 配置合并 性能考虑: 1. 切片展开有一定开销 2. 大量参数时考虑直接传递切片 3. 避免在热点代码中过度使用 4. 考虑内存分配的影响 */