初始提交

This commit is contained in:
2025-08-24 01:01:26 +08:00
commit e51feb1296
35 changed files with 9348 additions and 0 deletions

View File

@@ -0,0 +1,722 @@
/*
01-basic-functions.go - Go 语言基础函数详解
学习目标:
1. 掌握函数的基本语法和定义
2. 理解函数参数和返回值
3. 学会函数的调用方式
4. 了解函数的作用域规则
5. 掌握函数的实际应用
知识点:
- 函数定义语法
- 参数传递(值传递)
- 返回值
- 函数调用
- 函数作为值
- 匿名函数
- 递归函数
- 函数作用域
*/
package main
import (
"fmt"
"math"
"strings"
)
func main() {
fmt.Println("=== Go 语言基础函数详解 ===\n")
// 演示基本函数定义和调用
demonstrateBasicFunctions()
// 演示函数参数
demonstrateFunctionParameters()
// 演示函数返回值
demonstrateFunctionReturns()
// 演示函数作为值
demonstrateFunctionAsValue()
// 演示匿名函数
demonstrateAnonymousFunctions()
// 演示递归函数
demonstrateRecursiveFunctions()
// 演示函数作用域
demonstrateFunctionScope()
// 演示实际应用示例
demonstratePracticalExamples()
}
// demonstrateBasicFunctions 演示基本函数定义和调用
func demonstrateBasicFunctions() {
fmt.Println("1. 基本函数定义和调用:")
// 调用无参数无返回值的函数
fmt.Printf(" 调用无参数无返回值的函数:\n")
sayHello()
// 调用有参数无返回值的函数
fmt.Printf(" 调用有参数无返回值的函数:\n")
greetPerson("Alice")
greetPerson("Bob")
// 调用有参数有返回值的函数
fmt.Printf(" 调用有参数有返回值的函数:\n")
result := add(10, 20)
fmt.Printf(" add(10, 20) = %d\n", result)
// 直接在表达式中使用函数调用
fmt.Printf(" add(5, 7) * 2 = %d\n", add(5, 7)*2)
// 函数调用作为参数
fmt.Printf(" add(add(1, 2), add(3, 4)) = %d\n", add(add(1, 2), add(3, 4)))
fmt.Println()
}
// demonstrateFunctionParameters 演示函数参数
func demonstrateFunctionParameters() {
fmt.Println("2. 函数参数:")
// 单个参数
fmt.Printf(" 单个参数:\n")
square := calculateSquare(5)
fmt.Printf(" calculateSquare(5) = %d\n", square)
// 多个参数
fmt.Printf(" 多个参数:\n")
area := calculateRectangleArea(4, 6)
fmt.Printf(" calculateRectangleArea(4, 6) = %d\n", area)
// 相同类型的多个参数
fmt.Printf(" 相同类型的多个参数:\n")
max := findMax(15, 8, 23, 4, 19)
fmt.Printf(" findMax(15, 8, 23, 4, 19) = %d\n", max)
// 不同类型的参数
fmt.Printf(" 不同类型的参数:\n")
info := formatPersonInfo("Charlie", 25, 175.5)
fmt.Printf(" %s\n", info)
// 参数是值传递
fmt.Printf(" 参数是值传递(不会修改原变量):\n")
x := 10
fmt.Printf(" 修改前: x = %d\n", x)
tryToModify(x)
fmt.Printf(" 修改后: x = %d (未改变)\n", x)
// 传递切片(引用类型)
fmt.Printf(" 传递切片(引用类型):\n")
numbers := []int{1, 2, 3, 4, 5}
fmt.Printf(" 修改前: %v\n", numbers)
modifySlice(numbers)
fmt.Printf(" 修改后: %v (已改变)\n", numbers)
fmt.Println()
}
// demonstrateFunctionReturns 演示函数返回值
func demonstrateFunctionReturns() {
fmt.Println("3. 函数返回值:")
// 单个返回值
fmt.Printf(" 单个返回值:\n")
length := getStringLength("Hello, World!")
fmt.Printf(" 字符串长度: %d\n", length)
// 多个返回值
fmt.Printf(" 多个返回值:\n")
quotient, remainder := divide(17, 5)
fmt.Printf(" 17 ÷ 5 = %d 余 %d\n", quotient, remainder)
// 命名返回值
fmt.Printf(" 命名返回值:\n")
min, max := findMinMax([]int{3, 7, 1, 9, 4, 6})
fmt.Printf(" 数组 [3, 7, 1, 9, 4, 6] 的最小值: %d, 最大值: %d\n", min, max)
// 忽略某些返回值
fmt.Printf(" 忽略某些返回值:\n")
_, rem := divide(20, 3)
fmt.Printf(" 20 ÷ 3 的余数: %d\n", rem)
// 返回函数
fmt.Printf(" 返回函数:\n")
multiplier := getMultiplier(3)
result := multiplier(10)
fmt.Printf(" 3倍数函数应用于10: %d\n", result)
fmt.Println()
}
// demonstrateFunctionAsValue 演示函数作为值
func demonstrateFunctionAsValue() {
fmt.Println("4. 函数作为值:")
// 将函数赋值给变量
fmt.Printf(" 将函数赋值给变量:\n")
var operation func(int, int) int
operation = add
fmt.Printf(" operation = add; operation(5, 3) = %d\n", operation(5, 3))
operation = multiply
fmt.Printf(" operation = multiply; operation(5, 3) = %d\n", operation(5, 3))
// 函数作为参数
fmt.Printf(" 函数作为参数:\n")
numbers := []int{1, 2, 3, 4, 5}
result1 := applyOperation(numbers, double)
fmt.Printf(" 应用 double 函数: %v -> %v\n", numbers, result1)
result2 := applyOperation(numbers, square)
fmt.Printf(" 应用 square 函数: %v -> %v\n", numbers, result2)
// 函数切片
fmt.Printf(" 函数切片:\n")
operations := []func(int, int) int{add, subtract, multiply}
operationNames := []string{"加法", "减法", "乘法"}
a, b := 12, 4
for i, op := range operations {
result := op(a, b)
fmt.Printf(" %s: %d %s %d = %d\n", operationNames[i], a, getOperatorSymbol(i), b, result)
}
fmt.Println()
}
// demonstrateAnonymousFunctions 演示匿名函数
func demonstrateAnonymousFunctions() {
fmt.Println("5. 匿名函数:")
// 基本匿名函数
fmt.Printf(" 基本匿名函数:\n")
result := func(x, y int) int {
return x*x + y*y
}(3, 4)
fmt.Printf(" 匿名函数计算 3² + 4² = %d\n", result)
// 将匿名函数赋值给变量
fmt.Printf(" 将匿名函数赋值给变量:\n")
isEven := func(n int) bool {
return n%2 == 0
}
for i := 1; i <= 5; i++ {
fmt.Printf(" %d 是偶数: %t\n", i, isEven(i))
}
// 匿名函数作为参数
fmt.Printf(" 匿名函数作为参数:\n")
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
evenNumbers := filter(numbers, func(n int) bool {
return n%2 == 0
})
fmt.Printf(" 偶数: %v\n", evenNumbers)
largeNumbers := filter(numbers, func(n int) bool {
return n > 5
})
fmt.Printf(" 大于5的数: %v\n", largeNumbers)
// 匿名函数闭包
fmt.Printf(" 匿名函数闭包:\n")
counter := func() func() int {
count := 0
return func() int {
count++
return count
}
}()
fmt.Printf(" 计数器调用1: %d\n", counter())
fmt.Printf(" 计数器调用2: %d\n", counter())
fmt.Printf(" 计数器调用3: %d\n", counter())
fmt.Println()
}
// demonstrateRecursiveFunctions 演示递归函数
func demonstrateRecursiveFunctions() {
fmt.Println("6. 递归函数:")
// 阶乘函数
fmt.Printf(" 阶乘函数:\n")
for i := 0; i <= 5; i++ {
fact := factorial(i)
fmt.Printf(" %d! = %d\n", i, fact)
}
// 斐波那契数列
fmt.Printf(" 斐波那契数列:\n")
fmt.Printf(" 前10个斐波那契数: ")
for i := 0; i < 10; i++ {
fmt.Printf("%d ", fibonacci(i))
}
fmt.Printf("\n")
// 二分查找
fmt.Printf(" 二分查找:\n")
sortedArray := []int{1, 3, 5, 7, 9, 11, 13, 15, 17, 19}
target := 7
index := binarySearch(sortedArray, target, 0, len(sortedArray)-1)
if index != -1 {
fmt.Printf(" 在数组 %v 中找到 %d索引: %d\n", sortedArray, target, index)
} else {
fmt.Printf(" 在数组 %v 中未找到 %d\n", sortedArray, target)
}
// 计算数字各位数之和
fmt.Printf(" 计算数字各位数之和:\n")
number := 12345
digitSum := sumOfDigits(number)
fmt.Printf(" %d 的各位数之和: %d\n", number, digitSum)
fmt.Println()
}
// demonstrateFunctionScope 演示函数作用域
func demonstrateFunctionScope() {
fmt.Println("7. 函数作用域:")
// 全局变量
fmt.Printf(" 全局变量: globalVar = %s\n", globalVar)
// 局部变量
fmt.Printf(" 局部变量:\n")
localVar := "这是局部变量"
fmt.Printf(" localVar = %s\n", localVar)
// 函数内部的作用域
fmt.Printf(" 函数内部的作用域:\n")
testScope()
// 参数作用域
fmt.Printf(" 参数作用域:\n")
testParameterScope("参数值")
// 变量遮蔽
fmt.Printf(" 变量遮蔽:\n")
testVariableShadowing()
fmt.Println()
}
// demonstratePracticalExamples 演示实际应用示例
func demonstratePracticalExamples() {
fmt.Println("8. 实际应用示例:")
// 示例1: 数据处理函数
fmt.Printf(" 示例1 - 学生成绩处理:\n")
scores := []int{85, 92, 78, 96, 88, 73, 91, 87}
avg := calculateAverage(scores)
fmt.Printf(" 平均分: %.2f\n", avg)
grade := getLetterGrade(avg)
fmt.Printf(" 等级: %s\n", grade)
passCount := countPassingScores(scores, 80)
fmt.Printf(" 80分以上人数: %d/%d\n", passCount, len(scores))
// 示例2: 字符串处理函数
fmt.Printf(" 示例2 - 文本处理:\n")
text := "Hello, World! This is a test."
wordCount := countWords(text)
fmt.Printf(" 文本: \"%s\"\n", text)
fmt.Printf(" 单词数: %d\n", wordCount)
reversed := reverseString(text)
fmt.Printf(" 反转: \"%s\"\n", reversed)
isPalindrome := checkPalindrome("racecar")
fmt.Printf(" \"racecar\" 是回文: %t\n", isPalindrome)
// 示例3: 数学计算函数
fmt.Printf(" 示例3 - 几何计算:\n")
circleArea := calculateCircleArea(5.0)
fmt.Printf(" 半径5的圆面积: %.2f\n", circleArea)
triangleArea := calculateTriangleArea(3.0, 4.0, 5.0)
fmt.Printf(" 边长3,4,5的三角形面积: %.2f\n", triangleArea)
distance := calculateDistance(0, 0, 3, 4)
fmt.Printf(" 点(0,0)到点(3,4)的距离: %.2f\n", distance)
// 示例4: 数据验证函数
fmt.Printf(" 示例4 - 数据验证:\n")
emails := []string{
"user@example.com",
"invalid-email",
"test@domain.org",
}
for _, email := range emails {
isValid := validateEmail(email)
fmt.Printf(" 邮箱 \"%s\" 有效: %t\n", email, isValid)
}
phone := "138-1234-5678"
isValidPhone := validatePhoneNumber(phone)
fmt.Printf(" 电话 \"%s\" 有效: %t\n", phone, isValidPhone)
fmt.Println()
}
// ========== 函数定义 ==========
// 全局变量
var globalVar = "全局变量"
// 无参数无返回值的函数
func sayHello() {
fmt.Printf(" Hello, World!\n")
}
// 有参数无返回值的函数
func greetPerson(name string) {
fmt.Printf(" Hello, %s!\n", name)
}
// 有参数有返回值的函数
func add(a, b int) int {
return a + b
}
// 单个参数函数
func calculateSquare(n int) int {
return n * n
}
// 多个参数函数
func calculateRectangleArea(width, height int) int {
return width * height
}
// 相同类型多个参数函数
func findMax(numbers ...int) int {
if len(numbers) == 0 {
return 0
}
max := numbers[0]
for _, num := range numbers {
if num > max {
max = num
}
}
return max
}
// 不同类型参数函数
func formatPersonInfo(name string, age int, height float64) string {
return fmt.Sprintf("姓名: %s, 年龄: %d, 身高: %.1fcm", name, age, height)
}
// 尝试修改参数(值传递)
func tryToModify(x int) {
x = 100
fmt.Printf(" 函数内部: x = %d\n", x)
}
// 修改切片
func modifySlice(slice []int) {
if len(slice) > 0 {
slice[0] = 999
}
}
// 单个返回值函数
func getStringLength(s string) int {
return len(s)
}
// 多个返回值函数
func divide(a, b int) (int, int) {
return a / b, a % b
}
// 命名返回值函数
func findMinMax(numbers []int) (min, max int) {
if len(numbers) == 0 {
return 0, 0
}
min, max = numbers[0], numbers[0]
for _, num := range numbers {
if num < min {
min = num
}
if num > max {
max = num
}
}
return // 自动返回命名的返回值
}
// 返回函数的函数
func getMultiplier(factor int) func(int) int {
return func(x int) int {
return x * factor
}
}
// 基本运算函数
func multiply(a, b int) int {
return a * b
}
func subtract(a, b int) int {
return a - b
}
// 应用操作函数
func applyOperation(numbers []int, operation func(int) int) []int {
result := make([]int, len(numbers))
for i, num := range numbers {
result[i] = operation(num)
}
return result
}
// 操作函数
func double(x int) int {
return x * 2
}
func square(x int) int {
return x * x
}
// 获取运算符符号
func getOperatorSymbol(index int) string {
symbols := []string{"+", "-", "×"}
if index < len(symbols) {
return symbols[index]
}
return "?"
}
// 过滤函数
func filter(numbers []int, predicate func(int) bool) []int {
var result []int
for _, num := range numbers {
if predicate(num) {
result = append(result, num)
}
}
return result
}
// 递归函数:阶乘
func factorial(n int) int {
if n <= 1 {
return 1
}
return n * factorial(n-1)
}
// 递归函数:斐波那契
func fibonacci(n int) int {
if n <= 1 {
return n
}
return fibonacci(n-1) + fibonacci(n-2)
}
// 递归函数:二分查找
func binarySearch(arr []int, target, left, right int) int {
if left > right {
return -1
}
mid := (left + right) / 2
if arr[mid] == target {
return mid
} else if arr[mid] > target {
return binarySearch(arr, target, left, mid-1)
} else {
return binarySearch(arr, target, mid+1, right)
}
}
// 递归函数:数字各位数之和
func sumOfDigits(n int) int {
if n < 10 {
return n
}
return n%10 + sumOfDigits(n/10)
}
// 作用域测试函数
func testScope() {
innerVar := "函数内部变量"
fmt.Printf(" innerVar = %s\n", innerVar)
if true {
blockVar := "块级变量"
fmt.Printf(" blockVar = %s\n", blockVar)
}
// blockVar 在这里不可访问
}
func testParameterScope(param string) {
fmt.Printf(" 参数 param = %s\n", param)
param = "修改后的参数"
fmt.Printf(" 修改后 param = %s\n", param)
}
func testVariableShadowing() {
x := "外层变量"
fmt.Printf(" 外层 x = %s\n", x)
if true {
x := "内层变量" // 遮蔽外层变量
fmt.Printf(" 内层 x = %s\n", x)
}
fmt.Printf(" 外层 x = %s (未被修改)\n", x)
}
// 实际应用函数
func calculateAverage(scores []int) float64 {
if len(scores) == 0 {
return 0
}
sum := 0
for _, score := range scores {
sum += score
}
return float64(sum) / float64(len(scores))
}
func getLetterGrade(average float64) string {
switch {
case average >= 90:
return "A"
case average >= 80:
return "B"
case average >= 70:
return "C"
case average >= 60:
return "D"
default:
return "F"
}
}
func countPassingScores(scores []int, threshold int) int {
count := 0
for _, score := range scores {
if score >= threshold {
count++
}
}
return count
}
func countWords(text string) int {
words := strings.Fields(text)
return len(words)
}
func reverseString(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
func checkPalindrome(s string) bool {
s = strings.ToLower(s)
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
if s[i] != s[j] {
return false
}
}
return true
}
func calculateCircleArea(radius float64) float64 {
return math.Pi * radius * radius
}
func calculateTriangleArea(a, b, c float64) float64 {
// 使用海伦公式
s := (a + b + c) / 2
return math.Sqrt(s * (s - a) * (s - b) * (s - c))
}
func calculateDistance(x1, y1, x2, y2 float64) float64 {
dx := x2 - x1
dy := y2 - y1
return math.Sqrt(dx*dx + dy*dy)
}
func validateEmail(email string) bool {
return strings.Contains(email, "@") && strings.Contains(email, ".")
}
func validatePhoneNumber(phone string) bool {
// 简单验证:包含数字和连字符
return strings.Contains(phone, "-") && len(phone) >= 10
}
/*
运行这个程序:
go run 01-basic-functions.go
学习要点:
1. 函数是 Go 程序的基本构建块
2. 函数定义语法func 函数名(参数列表) 返回类型 { 函数体 }
3. Go 支持多返回值,这是其特色功能之一
4. 参数传递是值传递,但引用类型(切片、映射等)传递的是引用
5. 函数可以作为值传递和赋值
6. 支持匿名函数和闭包
7. 递归函数需要有明确的终止条件
函数的组成部分:
1. func 关键字
2. 函数名
3. 参数列表(可选)
4. 返回类型(可选)
5. 函数体
函数特性:
1. 支持多返回值
2. 支持命名返回值
3. 函数是一等公民(可以作为值)
4. 支持匿名函数和闭包
5. 支持递归调用
最佳实践:
1. 函数名应该清晰表达功能
2. 保持函数简短和专注
3. 合理使用多返回值
4. 适当使用命名返回值提高可读性
5. 避免过深的递归调用
6. 考虑函数的副作用
常见应用场景:
1. 代码复用和模块化
2. 数据处理和计算
3. 输入验证和格式化
4. 算法实现
5. 业务逻辑封装
6. 工具函数库
*/

View File

@@ -0,0 +1,774 @@
/*
02-multiple-returns.go - Go 语言多返回值详解
学习目标:
1. 掌握多返回值的语法和用法
2. 理解命名返回值的优势
3. 学会错误处理的惯用模式
4. 了解多返回值的实际应用场景
5. 掌握返回值的最佳实践
知识点:
- 多返回值语法
- 命名返回值
- 错误处理模式
- 返回值解构
- 忽略返回值
- 多返回值的性能考虑
- 实际应用场景
*/
package main
import (
"errors"
"fmt"
"math"
"strconv"
"strings"
"time"
)
func main() {
fmt.Println("=== Go 语言多返回值详解 ===\n")
// 演示基本多返回值
demonstrateBasicMultipleReturns()
// 演示命名返回值
demonstrateNamedReturns()
// 演示错误处理模式
demonstrateErrorHandling()
// 演示返回值解构和忽略
demonstrateReturnValueHandling()
// 演示多返回值的实际应用
demonstratePracticalApplications()
// 演示多返回值的高级用法
demonstrateAdvancedUsage()
// 演示性能考虑
demonstratePerformanceConsiderations()
}
// demonstrateBasicMultipleReturns 演示基本多返回值
func demonstrateBasicMultipleReturns() {
fmt.Println("1. 基本多返回值:")
// 两个返回值
fmt.Printf(" 两个返回值:\n")
quotient, remainder := divmod(17, 5)
fmt.Printf(" 17 ÷ 5 = %d 余 %d\n", quotient, remainder)
// 三个返回值
fmt.Printf(" 三个返回值:\n")
min, max, avg := analyzeNumbers([]int{3, 7, 1, 9, 4, 6})
fmt.Printf(" 数组 [3, 7, 1, 9, 4, 6] - 最小值: %d, 最大值: %d, 平均值: %.2f\n", min, max, avg)
// 不同类型的返回值
fmt.Printf(" 不同类型的返回值:\n")
name, age, height, isStudent := getPersonInfo()
fmt.Printf(" 个人信息 - 姓名: %s, 年龄: %d, 身高: %.1fcm, 学生: %t\n",
name, age, height, isStudent)
// 返回值和错误
fmt.Printf(" 返回值和错误:\n")
result, err := safeDivide(10, 2)
if err != nil {
fmt.Printf(" 错误: %v\n", err)
} else {
fmt.Printf(" 10 ÷ 2 = %.2f\n", result)
}
result, err = safeDivide(10, 0)
if err != nil {
fmt.Printf(" 错误: %v\n", err)
} else {
fmt.Printf(" 10 ÷ 0 = %.2f\n", result)
}
fmt.Println()
}
// demonstrateNamedReturns 演示命名返回值
func demonstrateNamedReturns() {
fmt.Println("2. 命名返回值:")
// 基本命名返回值
fmt.Printf(" 基本命名返回值:\n")
area, perimeter := calculateRectangle(5, 3)
fmt.Printf(" 矩形 5×3 - 面积: %d, 周长: %d\n", area, perimeter)
// 命名返回值的提前返回
fmt.Printf(" 命名返回值的提前返回:\n")
score, grade, pass := evaluateScore(85)
fmt.Printf(" 分数 85 - 等级: %s, 是否及格: %t\n", grade, pass)
score, grade, pass = evaluateScore(45)
fmt.Printf(" 分数 45 - 等级: %s, 是否及格: %t\n", grade, pass)
// 复杂的命名返回值
fmt.Printf(" 复杂的命名返回值:\n")
valid, reason, suggestions := validatePassword("123")
fmt.Printf(" 密码 \"123\" - 有效: %t, 原因: %s\n", valid, reason)
if len(suggestions) > 0 {
fmt.Printf(" 建议: %v\n", suggestions)
}
valid, reason, suggestions = validatePassword("SecurePass123!")
fmt.Printf(" 密码 \"SecurePass123!\" - 有效: %t, 原因: %s\n", valid, reason)
fmt.Println()
}
// demonstrateErrorHandling 演示错误处理模式
func demonstrateErrorHandling() {
fmt.Println("3. 错误处理模式:")
// 标准错误处理模式
fmt.Printf(" 标准错误处理模式:\n")
// 字符串转整数
value, err := parseInteger("123")
if err != nil {
fmt.Printf(" 解析错误: %v\n", err)
} else {
fmt.Printf(" 解析成功: %d\n", value)
}
value, err = parseInteger("abc")
if err != nil {
fmt.Printf(" 解析错误: %v\n", err)
} else {
fmt.Printf(" 解析成功: %d\n", value)
}
// 文件操作模拟
fmt.Printf(" 文件操作模拟:\n")
content, err := readFile("config.txt")
if err != nil {
fmt.Printf(" 读取文件错误: %v\n", err)
} else {
fmt.Printf(" 文件内容: %s\n", content)
}
// 网络请求模拟
fmt.Printf(" 网络请求模拟:\n")
data, statusCode, err := httpGet("https://api.example.com/users")
if err != nil {
fmt.Printf(" 请求错误: %v\n", err)
} else {
fmt.Printf(" 状态码: %d, 数据长度: %d\n", statusCode, len(data))
}
// 多层错误处理
fmt.Printf(" 多层错误处理:\n")
result, err := processUserData("user123")
if err != nil {
fmt.Printf(" 处理用户数据错误: %v\n", err)
} else {
fmt.Printf(" 处理结果: %s\n", result)
}
fmt.Println()
}
// demonstrateReturnValueHandling 演示返回值解构和忽略
func demonstrateReturnValueHandling() {
fmt.Println("4. 返回值解构和忽略:")
// 接收所有返回值
fmt.Printf(" 接收所有返回值:\n")
x, y, z := getCoordinates()
fmt.Printf(" 坐标: (%d, %d, %d)\n", x, y, z)
// 忽略某些返回值
fmt.Printf(" 忽略某些返回值:\n")
_, _, avgZ := getCoordinates()
fmt.Printf(" 只关心 Z 坐标: %d\n", avgZ)
// 只检查错误
fmt.Printf(" 只检查错误:\n")
_, err := safeDivide(10, 2)
if err != nil {
fmt.Printf(" 操作失败: %v\n", err)
} else {
fmt.Printf(" 操作成功\n")
}
// 链式调用
fmt.Printf(" 链式调用:\n")
result, err := processChain("input")
if err != nil {
fmt.Printf(" 链式处理错误: %v\n", err)
} else {
fmt.Printf(" 链式处理结果: %s\n", result)
}
// 多重赋值
fmt.Printf(" 多重赋值:\n")
a, b := 10, 20
fmt.Printf(" 交换前: a=%d, b=%d\n", a, b)
a, b = swap(a, b)
fmt.Printf(" 交换后: a=%d, b=%d\n", a, b)
fmt.Println()
}
// demonstratePracticalApplications 演示多返回值的实际应用
func demonstratePracticalApplications() {
fmt.Println("5. 多返回值的实际应用:")
// 应用1: 数据库查询模拟
fmt.Printf(" 应用1 - 数据库查询模拟:\n")
user, found, err := findUserByID(123)
if err != nil {
fmt.Printf(" 查询错误: %v\n", err)
} else if !found {
fmt.Printf(" 用户不存在\n")
} else {
fmt.Printf(" 找到用户: %+v\n", user)
}
// 应用2: 缓存操作
fmt.Printf(" 应用2 - 缓存操作:\n")
value, hit, err := getFromCache("user:123")
if err != nil {
fmt.Printf(" 缓存错误: %v\n", err)
} else if hit {
fmt.Printf(" 缓存命中: %s\n", value)
} else {
fmt.Printf(" 缓存未命中\n")
}
// 应用3: 配置解析
fmt.Printf(" 应用3 - 配置解析:\n")
config, warnings, err := parseConfig("app.conf")
if err != nil {
fmt.Printf(" 配置解析错误: %v\n", err)
} else {
fmt.Printf(" 配置加载成功: %+v\n", config)
if len(warnings) > 0 {
fmt.Printf(" 警告: %v\n", warnings)
}
}
// 应用4: 数据验证
fmt.Printf(" 应用4 - 数据验证:\n")
userData := map[string]string{
"name": "Alice",
"email": "alice@example.com",
"age": "25",
}
valid, errors := validateUserData(userData)
fmt.Printf(" 用户数据验证 - 有效: %t\n", valid)
if len(errors) > 0 {
fmt.Printf(" 验证错误: %v\n", errors)
}
// 应用5: 统计分析
fmt.Printf(" 应用5 - 统计分析:\n")
data := []float64{1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0}
mean, median, stddev := calculateStatistics(data)
fmt.Printf(" 数据: %v\n", data)
fmt.Printf(" 统计结果 - 平均值: %.2f, 中位数: %.2f, 标准差: %.2f\n",
mean, median, stddev)
fmt.Println()
}
// demonstrateAdvancedUsage 演示多返回值的高级用法
func demonstrateAdvancedUsage() {
fmt.Println("6. 多返回值的高级用法:")
// 返回函数
fmt.Printf(" 返回函数:\n")
add, multiply := getMathOperations()
fmt.Printf(" add(5, 3) = %d\n", add(5, 3))
fmt.Printf(" multiply(5, 3) = %d\n", multiply(5, 3))
// 返回接口
fmt.Printf(" 返回接口:\n")
reader, writer := getIOOperations()
data := []byte("Hello, World!")
n, err := writer.Write(data)
if err != nil {
fmt.Printf(" 写入错误: %v\n", err)
} else {
fmt.Printf(" 写入 %d 字节\n", n)
}
buffer := make([]byte, 13)
n, err = reader.Read(buffer)
if err != nil {
fmt.Printf(" 读取错误: %v\n", err)
} else {
fmt.Printf(" 读取 %d 字节: %s\n", n, string(buffer[:n]))
}
// 返回通道
fmt.Printf(" 返回通道:\n")
input, output := createPipeline()
// 发送数据
go func() {
for i := 1; i <= 3; i++ {
input <- i
}
close(input)
}()
// 接收处理后的数据
for result := range output {
fmt.Printf(" 处理结果: %d\n", result)
}
fmt.Println()
}
// demonstratePerformanceConsiderations 演示性能考虑
func demonstratePerformanceConsiderations() {
fmt.Println("7. 性能考虑:")
// 返回值的内存分配
fmt.Printf(" 返回值的内存分配:\n")
// 返回值拷贝 vs 返回指针
largeData := make([]int, 1000)
for i := range largeData {
largeData[i] = i
}
// 返回拷贝(可能影响性能)
copied, size := copyLargeData(largeData)
fmt.Printf(" 返回拷贝 - 大小: %d, 第一个元素: %d\n", size, copied[0])
// 返回指针(更高效)
ptr, size := referenceLargeData(largeData)
fmt.Printf(" 返回指针 - 大小: %d, 第一个元素: %d\n", size, (*ptr)[0])
// 多返回值 vs 结构体
fmt.Printf(" 多返回值 vs 结构体:\n")
// 使用多返回值
name, age, email := getUserInfo1()
fmt.Printf(" 多返回值: %s, %d, %s\n", name, age, email)
// 使用结构体
user := getUserInfo2()
fmt.Printf(" 结构体: %s, %d, %s\n", user.Name, user.Age, user.Email)
// 错误处理的性能
fmt.Printf(" 错误处理的性能:\n")
// 正常情况
start := time.Now()
for i := 0; i < 1000; i++ {
_, err := fastOperation(i)
if err != nil {
// 处理错误
}
}
duration := time.Since(start)
fmt.Printf(" 1000次正常操作耗时: %v\n", duration)
fmt.Println()
}
// ========== 函数定义 ==========
// 基本多返回值函数
func divmod(a, b int) (int, int) {
return a / b, a % b
}
func analyzeNumbers(numbers []int) (int, int, float64) {
if len(numbers) == 0 {
return 0, 0, 0
}
min, max := numbers[0], numbers[0]
sum := 0
for _, num := range numbers {
if num < min {
min = num
}
if num > max {
max = num
}
sum += num
}
avg := float64(sum) / float64(len(numbers))
return min, max, avg
}
func getPersonInfo() (string, int, float64, bool) {
return "Alice", 25, 165.5, true
}
func safeDivide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("除数不能为零")
}
return a / b, nil
}
// 命名返回值函数
func calculateRectangle(width, height int) (area, perimeter int) {
area = width * height
perimeter = 2 * (width + height)
return // 自动返回命名的返回值
}
func evaluateScore(score int) (originalScore int, grade string, pass bool) {
originalScore = score
if score < 0 || score > 100 {
grade = "无效"
return // 提前返回
}
switch {
case score >= 90:
grade = "A"
case score >= 80:
grade = "B"
case score >= 70:
grade = "C"
case score >= 60:
grade = "D"
default:
grade = "F"
}
pass = score >= 60
return
}
func validatePassword(password string) (valid bool, reason string, suggestions []string) {
if len(password) < 8 {
reason = "密码长度不足8位"
suggestions = append(suggestions, "增加密码长度")
return
}
hasUpper := strings.ContainsAny(password, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
hasLower := strings.ContainsAny(password, "abcdefghijklmnopqrstuvwxyz")
hasDigit := strings.ContainsAny(password, "0123456789")
hasSpecial := strings.ContainsAny(password, "!@#$%^&*")
if !hasUpper {
suggestions = append(suggestions, "添加大写字母")
}
if !hasLower {
suggestions = append(suggestions, "添加小写字母")
}
if !hasDigit {
suggestions = append(suggestions, "添加数字")
}
if !hasSpecial {
suggestions = append(suggestions, "添加特殊字符")
}
if hasUpper && hasLower && hasDigit && hasSpecial {
valid = true
reason = "密码强度良好"
} else {
reason = "密码强度不足"
}
return
}
// 错误处理函数
func parseInteger(s string) (int, error) {
value, err := strconv.Atoi(s)
if err != nil {
return 0, fmt.Errorf("无法解析整数 '%s': %w", s, err)
}
return value, nil
}
func readFile(filename string) (string, error) {
// 模拟文件读取
if filename == "config.txt" {
return "server_port=8080\ndebug=true", nil
}
return "", fmt.Errorf("文件 '%s' 不存在", filename)
}
func httpGet(url string) ([]byte, int, error) {
// 模拟HTTP请求
if strings.Contains(url, "example.com") {
return []byte(`{"users": [{"id": 1, "name": "Alice"}]}`), 200, nil
}
return nil, 0, errors.New("网络连接失败")
}
func processUserData(userID string) (string, error) {
// 模拟多层处理
if userID == "" {
return "", errors.New("用户ID不能为空")
}
// 模拟数据库查询
if userID == "user123" {
return "用户数据处理完成", nil
}
return "", fmt.Errorf("用户 '%s' 不存在", userID)
}
// 返回值处理函数
func getCoordinates() (int, int, int) {
return 10, 20, 30
}
func processChain(input string) (string, error) {
if input == "" {
return "", errors.New("输入不能为空")
}
// 模拟处理链
step1 := strings.ToUpper(input)
step2 := step1 + "_PROCESSED"
return step2, nil
}
func swap(a, b int) (int, int) {
return b, a
}
// 实际应用函数
type User struct {
ID int
Name string
Email string
}
func findUserByID(id int) (User, bool, error) {
// 模拟数据库查询
if id <= 0 {
return User{}, false, errors.New("无效的用户ID")
}
if id == 123 {
return User{ID: 123, Name: "Alice", Email: "alice@example.com"}, true, nil
}
return User{}, false, nil
}
func getFromCache(key string) (string, bool, error) {
// 模拟缓存操作
cache := map[string]string{
"user:123": "Alice",
"user:456": "Bob",
}
if value, exists := cache[key]; exists {
return value, true, nil
}
return "", false, nil
}
type Config struct {
Port int
Debug bool
Timeout int
}
func parseConfig(filename string) (Config, []string, error) {
// 模拟配置解析
config := Config{Port: 8080, Debug: true, Timeout: 30}
warnings := []string{"使用默认超时值"}
if filename == "app.conf" {
return config, warnings, nil
}
return Config{}, nil, fmt.Errorf("配置文件 '%s' 不存在", filename)
}
func validateUserData(data map[string]string) (bool, []string) {
var errors []string
if name := data["name"]; name == "" {
errors = append(errors, "姓名不能为空")
}
if email := data["email"]; !strings.Contains(email, "@") {
errors = append(errors, "邮箱格式无效")
}
if ageStr := data["age"]; ageStr != "" {
if age, err := strconv.Atoi(ageStr); err != nil || age < 0 || age > 150 {
errors = append(errors, "年龄无效")
}
}
return len(errors) == 0, errors
}
func calculateStatistics(data []float64) (mean, median, stddev float64) {
if len(data) == 0 {
return 0, 0, 0
}
// 计算平均值
sum := 0.0
for _, v := range data {
sum += v
}
mean = sum / float64(len(data))
// 计算中位数(简化版)
median = data[len(data)/2]
// 计算标准差
variance := 0.0
for _, v := range data {
variance += (v - mean) * (v - mean)
}
stddev = math.Sqrt(variance / float64(len(data)))
return
}
// 高级用法函数
func getMathOperations() (func(int, int) int, func(int, int) int) {
add := func(a, b int) int { return a + b }
multiply := func(a, b int) int { return a * b }
return add, multiply
}
type MockReader struct {
data []byte
pos int
}
func (r *MockReader) Read(p []byte) (n int, error) {
if r.pos >= len(r.data) {
return 0, errors.New("EOF")
}
n = copy(p, r.data[r.pos:])
r.pos += n
return n, nil
}
type MockWriter struct {
data []byte
}
func (w *MockWriter) Write(p []byte) (n int, error) {
w.data = append(w.data, p...)
return len(p), nil
}
func getIOOperations() (*MockReader, *MockWriter) {
reader := &MockReader{data: []byte("Hello, World!")}
writer := &MockWriter{}
return reader, writer
}
func createPipeline() (chan<- int, <-chan int) {
input := make(chan int)
output := make(chan int)
go func() {
defer close(output)
for value := range input {
output <- value * 2 // 处理数据
}
}()
return input, output
}
// 性能考虑函数
func copyLargeData(data []int) ([]int, int) {
copied := make([]int, len(data))
copy(copied, data)
return copied, len(copied)
}
func referenceLargeData(data []int) (*[]int, int) {
return &data, len(data)
}
func getUserInfo1() (string, int, string) {
return "Alice", 25, "alice@example.com"
}
type UserInfo struct {
Name string
Age int
Email string
}
func getUserInfo2() UserInfo {
return UserInfo{Name: "Alice", Age: 25, Email: "alice@example.com"}
}
func fastOperation(n int) (int, error) {
if n < 0 {
return 0, errors.New("负数")
}
return n * 2, nil
}
/*
运行这个程序:
go run 02-multiple-returns.go
学习要点:
1. Go 支持多返回值,这是其独特且强大的特性
2. 多返回值常用于返回结果和错误信息
3. 命名返回值可以提高代码可读性,支持提前返回
4. 可以使用 _ 忽略不需要的返回值
5. 多返回值是 Go 错误处理的基础
多返回值的优势:
1. 避免使用指针参数传递多个结果
2. 使错误处理更加明确和一致
3. 提高代码的可读性和维护性
4. 支持函数式编程风格
常见模式:
1. (result, error) - 标准错误处理模式
2. (value, ok) - 检查操作是否成功
3. (value, found, error) - 查询操作模式
4. 命名返回值 - 提高可读性
最佳实践:
1. 错误通常作为最后一个返回值
2. 使用命名返回值提高复杂函数的可读性
3. 适当使用 _ 忽略不需要的返回值
4. 保持返回值数量合理通常不超过3-4个
5. 考虑使用结构体替代过多的返回值
性能考虑:
1. 多返回值通常比传递指针参数更高效
2. 大对象考虑返回指针而不是值拷贝
3. 命名返回值可能有轻微的性能开销
4. 错误处理的性能影响通常可以忽略
应用场景:
1. 错误处理
2. 数据库查询
3. 网络操作
4. 文件操作
5. 数据验证
6. 统计计算
7. 缓存操作
*/

View File

@@ -0,0 +1,757 @@
/*
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. 考虑内存分配的影响
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,869 @@
/*
05-methods.go - Go 语言方法详解
学习目标:
1. 理解方法与函数的区别
2. 掌握方法的定义和调用
3. 学会值接收者和指针接收者的使用
4. 了解方法集的概念
5. 掌握方法的实际应用
知识点:
- 方法定义语法
- 值接收者 vs 指针接收者
- 方法集和接口实现
- 方法的继承和组合
- 方法的实际应用场景
*/
package main
import (
"fmt"
)
func main() {
fmt.Println("=== Go 语言方法详解 ===\n")
// 演示基本方法定义和调用
demonstrateBasicMethods()
// 演示值接收者和指针接收者
demonstrateReceiverTypes()
// 演示方法集和接口实现
demonstrateMethodSets()
// 演示方法的继承和组合
demonstrateMethodComposition()
// 演示方法的实际应用
demonstratePracticalApplications()
// 演示方法的高级用法
demonstrateAdvancedMethodUsage()
}
// demonstrateBasicMethods 演示基本方法定义和调用
func demonstrateBasicMethods() {
fmt.Println("1. 基本方法定义和调用:")
// 创建结构体实例
fmt.Printf(" 创建和使用基本方法:\n")
rect := Rectangle{Width: 10, Height: 5}
fmt.Printf(" 矩形: %+v\n", rect)
fmt.Printf(" 面积: %.2f\n", rect.Area())
fmt.Printf(" 周长: %.2f\n", rect.Perimeter())
// 方法链调用
fmt.Printf(" 方法链调用:\n")
rect.SetWidth(8).SetHeight(6)
fmt.Printf(" 修改后的矩形: %+v\n", rect)
fmt.Printf(" 新面积: %.2f\n", rect.Area())
// 不同类型的方法
fmt.Printf(" 不同类型的方法:\n")
circle := Circle{Radius: 3}
fmt.Printf(" 圆形: %+v\n", circle)
fmt.Printf(" 面积: %.2f\n", circle.Area())
fmt.Printf(" 周长: %.2f\n", circle.Circumference())
// 基本类型的方法
fmt.Printf(" 基本类型的方法:\n")
var temp Temperature = 25.5
fmt.Printf(" 温度: %.1f°C\n", temp)
fmt.Printf(" 华氏度: %.1f°F\n", temp.ToFahrenheit())
fmt.Printf(" 开尔文: %.1f K\n", temp.ToKelvin())
fmt.Println()
}// demonstr
ateReceiverTypes 演示值接收者和指针接收者
func demonstrateReceiverTypes() {
fmt.Println("2. 值接收者和指针接收者:")
// 值接收者示例
fmt.Printf(" 值接收者示例:\n")
counter1 := Counter{Value: 0}
fmt.Printf(" 初始计数器: %+v\n", counter1)
// 值接收者方法不会修改原始值
counter1.IncrementByValue()
fmt.Printf(" 值接收者增加后: %+v\n", counter1) // 值不变
// 指针接收者示例
fmt.Printf(" 指针接收者示例:\n")
counter2 := Counter{Value: 0}
fmt.Printf(" 初始计数器: %+v\n", counter2)
// 指针接收者方法会修改原始值
counter2.IncrementByPointer()
fmt.Printf(" 指针接收者增加后: %+v\n", counter2) // 值改变
// 方法调用的自动转换
fmt.Printf(" 方法调用的自动转换:\n")
counter3 := Counter{Value: 10}
counterPtr := &counter3
// 值类型可以调用指针接收者方法(自动取地址)
counter3.IncrementByPointer()
fmt.Printf(" 值类型调用指针方法: %+v\n", counter3)
// 指针类型可以调用值接收者方法(自动解引用)
result := counterPtr.GetValueCopy()
fmt.Printf(" 指针类型调用值方法: %d\n", result)
// 大结构体的性能考虑
fmt.Printf(" 大结构体的性能考虑:\n")
largeStruct := LargeStruct{}
for i := 0; i < 1000; i++ {
largeStruct.Data[i] = i
}
// 值接收者会拷贝整个结构体
start := time.Now()
largeStruct.ProcessByValue()
valueTime := time.Since(start)
// 指针接收者只传递指针
start = time.Now()
largeStruct.ProcessByPointer()
pointerTime := time.Since(start)
fmt.Printf(" 值接收者耗时: %v\n", valueTime)
fmt.Printf(" 指针接收者耗时: %v\n", pointerTime)
fmt.Println()
}
// demonstrateMethodSets 演示方法集和接口实现
func demonstrateMethodSets() {
fmt.Println("3. 方法集和接口实现:")
// 接口实现
fmt.Printf(" 接口实现:\n")
var shapes []Shape
shapes = append(shapes, Rectangle{Width: 4, Height: 3})
shapes = append(shapes, Circle{Radius: 2})
shapes = append(shapes, Triangle{Base: 6, Height: 4})
totalArea := 0.0
for i, shape := range shapes {
area := shape.Area()
fmt.Printf(" 形状 %d 面积: %.2f\n", i+1, area)
totalArea += area
}
fmt.Printf(" 总面积: %.2f\n", totalArea)
// 方法集的规则
fmt.Printf(" 方法集的规则:\n")
// 值类型的方法集
var drawable1 Drawable = Rectangle{Width: 5, Height: 3}
drawable1.Draw()
// 指针类型的方法集
rect := Rectangle{Width: 5, Height: 3}
var drawable2 Drawable = &rect
drawable2.Draw()
// 可修改接口
fmt.Printf(" 可修改接口:\n")
var modifiable Modifiable = &rect
fmt.Printf(" 修改前: %+v\n", rect)
modifiable.Modify()
fmt.Printf(" 修改后: %+v\n", rect)
// 注意:值类型不能实现需要指针接收者的接口
// var modifiable2 Modifiable = rect // 编译错误
fmt.Println()
}
// demonstrateMethodComposition 演示方法的继承和组合
func demonstrateMethodComposition() {
fmt.Println("4. 方法的继承和组合:")
// 结构体嵌入
fmt.Printf(" 结构体嵌入:\n")
person := Person{
Name: "Alice",
Age: 30,
}
employee := Employee{
Person: person,
JobTitle: "软件工程师",
Salary: 80000,
}
// 可以直接调用嵌入类型的方法
fmt.Printf(" 员工信息: %s\n", employee.GetInfo())
fmt.Printf(" 员工详情: %s\n", employee.GetDetails())
// 匿名嵌入
fmt.Printf(" 匿名嵌入:\n")
manager := Manager{
Person: Person{
Name: "Bob",
Age: 35,
},
Department: "技术部",
TeamSize: 10,
}
// 直接访问嵌入类型的方法和字段
fmt.Printf(" 经理姓名: %s\n", manager.Name) // 直接访问嵌入字段
fmt.Printf(" 经理信息: %s\n", manager.GetInfo()) // 直接调用嵌入方法
fmt.Printf(" 管理信息: %s\n", manager.Manage())
// 方法重写
fmt.Printf(" 方法重写:\n")
student := Student{
Person: Person{
Name: "Charlie",
Age: 20,
},
School: "清华大学",
Grade: "大三",
}
// Student 重写了 GetInfo 方法
fmt.Printf(" 学生信息: %s\n", student.GetInfo())
// 仍然可以访问原始方法
fmt.Printf(" 基础信息: %s\n", student.Person.GetInfo())
fmt.Println()
}// dem
onstratePracticalApplications 演示方法的实际应用
func demonstratePracticalApplications() {
fmt.Println("5. 方法的实际应用:")
// 应用1: 银行账户管理
fmt.Printf(" 应用1 - 银行账户管理:\n")
account := BankAccount{
AccountNumber: "123456789",
Balance: 1000.0,
Owner: "Alice",
}
fmt.Printf(" 初始账户: %s\n", account.GetInfo())
account.Deposit(500.0)
fmt.Printf(" 存款后: %s\n", account.GetInfo())
success := account.Withdraw(200.0)
fmt.Printf(" 取款成功: %t, 余额: %.2f\n", success, account.Balance)
success = account.Withdraw(2000.0)
fmt.Printf(" 取款成功: %t, 余额: %.2f\n", success, account.Balance)
// 应用2: 购物车系统
fmt.Printf(" 应用2 - 购物车系统:\n")
cart := ShoppingCart{}
cart.AddItem("笔记本电脑", 5999.99, 1)
cart.AddItem("鼠标", 99.99, 2)
cart.AddItem("键盘", 299.99, 1)
fmt.Printf(" 购物车内容:\n")
cart.DisplayItems()
fmt.Printf(" 总价: %.2f\n", cart.GetTotal())
cart.RemoveItem("鼠标")
fmt.Printf(" 移除鼠标后总价: %.2f\n", cart.GetTotal())
// 应用3: 日志记录器
fmt.Printf(" 应用3 - 日志记录器:\n")
logger := Logger{Level: "INFO"}
logger.Info("应用程序启动")
logger.Warning("配置文件使用默认值")
logger.Error("数据库连接失败")
logger.Debug("调试信息") // 不会显示,因为级别是 INFO
logger.SetLevel("DEBUG")
logger.Debug("现在可以看到调试信息了")
// 应用4: 配置管理器
fmt.Printf(" 应用4 - 配置管理器:\n")
config := Config{
settings: make(map[string]string),
}
config.Set("database.host", "localhost")
config.Set("database.port", "5432")
config.Set("app.debug", "true")
fmt.Printf(" 数据库主机: %s\n", config.Get("database.host"))
fmt.Printf(" 应用调试: %s\n", config.Get("app.debug"))
fmt.Printf(" 不存在的配置: %s\n", config.Get("nonexistent"))
fmt.Printf(" 所有配置:\n")
config.DisplayAll()
fmt.Println()
}
// demonstrateAdvancedMethodUsage 演示方法的高级用法
func demonstrateAdvancedMethodUsage() {
fmt.Println("6. 方法的高级用法:")
// 高级用法1: 方法表达式
fmt.Printf(" 高级用法1 - 方法表达式:\n")
rect := Rectangle{Width: 4, Height: 3}
// 方法表达式:将方法转换为函数
areaFunc := Rectangle.Area
perimeterFunc := Rectangle.Perimeter
fmt.Printf(" 使用方法表达式计算面积: %.2f\n", areaFunc(rect))
fmt.Printf(" 使用方法表达式计算周长: %.2f\n", perimeterFunc(rect))
// 高级用法2: 方法值
fmt.Printf(" 高级用法2 - 方法值:\n")
// 方法值:绑定到特定实例的方法
rectAreaMethod := rect.Area
rectPerimeterMethod := rect.Perimeter
fmt.Printf(" 使用方法值计算面积: %.2f\n", rectAreaMethod())
fmt.Printf(" 使用方法值计算周长: %.2f\n", rectPerimeterMethod())
// 高级用法3: 接口组合
fmt.Printf(" 高级用法3 - 接口组合:\n")
var readWriter ReadWriter = &File{Name: "test.txt"}
data := []byte("Hello, World!")
readWriter.Write(data)
buffer := make([]byte, 20)
n := readWriter.Read(buffer)
fmt.Printf(" 读取到 %d 字节: %s\n", n, string(buffer[:n]))
// 高级用法4: 类型断言和方法调用
fmt.Printf(" 高级用法4 - 类型断言和方法调用:\n")
var shape Shape = Circle{Radius: 5}
// 类型断言获取具体类型
if circle, ok := shape.(Circle); ok {
fmt.Printf(" 圆的半径: %.2f\n", circle.Radius)
fmt.Printf(" 圆的周长: %.2f\n", circle.Circumference())
}
// 高级用法5: 方法集的动态调用
fmt.Printf(" 高级用法5 - 方法集的动态调用:\n")
calculator := Calculator{}
operations := []struct {
name string
method func(float64, float64) float64
}{
{"加法", calculator.Add},
{"减法", calculator.Subtract},
{"乘法", calculator.Multiply},
{"除法", calculator.Divide},
}
a, b := 10.0, 3.0
for _, op := range operations {
result := op.method(a, b)
fmt.Printf(" %.1f %s %.1f = %.2f\n", a, op.name, b, result)
}
// 高级用法6: 链式方法调用
fmt.Printf(" 高级用法6 - 链式方法调用:\n")
builder := NewStringBuilder()
result := builder.
Append("Hello").
Append(" ").
Append("World").
Append("!").
ToUpper().
Build()
fmt.Printf(" 构建结果: %s\n", result)
fmt.Println()
}// =
========= 类型和方法定义 ==========
// 基本结构体和方法
type Rectangle struct {
Width float64
Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
// 指针接收者方法,支持方法链
func (r *Rectangle) SetWidth(width float64) *Rectangle {
r.Width = width
return r
}
func (r *Rectangle) SetHeight(height float64) *Rectangle {
r.Height = height
return r
}
func (r Rectangle) Draw() {
fmt.Printf(" 绘制矩形: %.1f x %.1f\n", r.Width, r.Height)
}
func (r *Rectangle) Modify() {
r.Width *= 1.1
r.Height *= 1.1
fmt.Printf(" 矩形已放大 10%%\n")
}
// 圆形结构体和方法
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
func (c Circle) Circumference() float64 {
return 2 * math.Pi * c.Radius
}
func (c Circle) Draw() {
fmt.Printf(" 绘制圆形: 半径 %.1f\n", c.Radius)
}
// 三角形结构体和方法
type Triangle struct {
Base float64
Height float64
}
func (t Triangle) Area() float64 {
return 0.5 * t.Base * t.Height
}
func (t Triangle) Draw() {
fmt.Printf(" 绘制三角形: 底边 %.1f, 高 %.1f\n", t.Base, t.Height)
}
// 基本类型的方法
type Temperature float64
func (t Temperature) ToFahrenheit() float64 {
return float64(t)*9/5 + 32
}
func (t Temperature) ToKelvin() float64 {
return float64(t) + 273.15
}
// 值接收者 vs 指针接收者示例
type Counter struct {
Value int
}
// 值接收者:不会修改原始值
func (c Counter) IncrementByValue() {
c.Value++
fmt.Printf(" 值接收者内部: %d\n", c.Value)
}
// 指针接收者:会修改原始值
func (c *Counter) IncrementByPointer() {
c.Value++
fmt.Printf(" 指针接收者内部: %d\n", c.Value)
}
func (c Counter) GetValueCopy() int {
return c.Value
}
// 大结构体性能测试
type LargeStruct struct {
Data [1000]int
}
func (ls LargeStruct) ProcessByValue() {
// 值接收者会拷贝整个结构体
sum := 0
for _, v := range ls.Data {
sum += v
}
}
func (ls *LargeStruct) ProcessByPointer() {
// 指针接收者只传递指针
sum := 0
for _, v := range ls.Data {
sum += v
}
}
// 接口定义
type Shape interface {
Area() float64
}
type Drawable interface {
Draw()
}
type Modifiable interface {
Modify()
}
// 组合接口
type ReadWriter interface {
Reader
Writer
}
type Reader interface {
Read([]byte) int
}
type Writer interface {
Write([]byte) int
}
// 文件类型实现 ReadWriter 接口
type File struct {
Name string
data []byte
}
func (f *File) Read(buffer []byte) int {
n := copy(buffer, f.data)
return n
}
func (f *File) Write(data []byte) int {
f.data = append(f.data, data...)
return len(data)
}
// 结构体嵌入示例
type Person struct {
Name string
Age int
}
func (p Person) GetInfo() string {
return fmt.Sprintf("%s (%d岁)", p.Name, p.Age)
}
type Employee struct {
Person // 具名嵌入
JobTitle string
Salary float64
}
func (e Employee) GetDetails() string {
return fmt.Sprintf("%s - %s, 薪资: %.0f", e.GetInfo(), e.JobTitle, e.Salary)
}
// 匿名嵌入
type Manager struct {
Person // 匿名嵌入
Department string
TeamSize int
}
func (m Manager) Manage() string {
return fmt.Sprintf("管理 %s团队规模: %d人", m.Department, m.TeamSize)
}
// 方法重写示例
type Student struct {
Person
School string
Grade string
}
// 重写 Person 的 GetInfo 方法
func (s Student) GetInfo() string {
return fmt.Sprintf("%s (%d岁) - %s %s", s.Name, s.Age, s.School, s.Grade)
}// 实际应用
示例
// 银行账户
type BankAccount struct {
AccountNumber string
Balance float64
Owner string
}
func (ba *BankAccount) Deposit(amount float64) {
if amount > 0 {
ba.Balance += amount
fmt.Printf(" 存款 %.2f,当前余额: %.2f\n", amount, ba.Balance)
}
}
func (ba *BankAccount) Withdraw(amount float64) bool {
if amount > 0 && amount <= ba.Balance {
ba.Balance -= amount
fmt.Printf(" 取款 %.2f,当前余额: %.2f\n", amount, ba.Balance)
return true
}
fmt.Printf(" 取款失败:余额不足或金额无效\n")
return false
}
func (ba BankAccount) GetInfo() string {
return fmt.Sprintf("账户: %s, 户主: %s, 余额: %.2f",
ba.AccountNumber, ba.Owner, ba.Balance)
}
// 购物车系统
type CartItem struct {
Name string
Price float64
Quantity int
}
type ShoppingCart struct {
Items []CartItem
}
func (sc *ShoppingCart) AddItem(name string, price float64, quantity int) {
// 检查是否已存在该商品
for i := range sc.Items {
if sc.Items[i].Name == name {
sc.Items[i].Quantity += quantity
return
}
}
// 添加新商品
sc.Items = append(sc.Items, CartItem{
Name: name,
Price: price,
Quantity: quantity,
})
}
func (sc *ShoppingCart) RemoveItem(name string) {
for i, item := range sc.Items {
if item.Name == name {
sc.Items = append(sc.Items[:i], sc.Items[i+1:]...)
return
}
}
}
func (sc ShoppingCart) GetTotal() float64 {
total := 0.0
for _, item := range sc.Items {
total += item.Price * float64(item.Quantity)
}
return total
}
func (sc ShoppingCart) DisplayItems() {
for _, item := range sc.Items {
fmt.Printf(" %s: %.2f × %d = %.2f\n",
item.Name, item.Price, item.Quantity,
item.Price*float64(item.Quantity))
}
}
// 日志记录器
type Logger struct {
Level string
}
func (l *Logger) SetLevel(level string) {
l.Level = level
}
func (l Logger) shouldLog(level string) bool {
levels := map[string]int{
"DEBUG": 0,
"INFO": 1,
"WARN": 2,
"ERROR": 3,
}
currentLevel := levels[l.Level]
messageLevel := levels[level]
return messageLevel >= currentLevel
}
func (l Logger) log(level, message string) {
if l.shouldLog(level) {
timestamp := time.Now().Format("2006-01-02 15:04:05")
fmt.Printf(" [%s] %s: %s\n", timestamp, level, message)
}
}
func (l Logger) Debug(message string) {
l.log("DEBUG", message)
}
func (l Logger) Info(message string) {
l.log("INFO", message)
}
func (l Logger) Warning(message string) {
l.log("WARN", message)
}
func (l Logger) Error(message string) {
l.log("ERROR", message)
}
// 配置管理器
type Config struct {
settings map[string]string
}
func (c *Config) Set(key, value string) {
c.settings[key] = value
}
func (c Config) Get(key string) string {
if value, exists := c.settings[key]; exists {
return value
}
return ""
}
func (c Config) DisplayAll() {
for key, value := range c.settings {
fmt.Printf(" %s = %s\n", key, value)
}
}
// 计算器
type Calculator struct{}
func (calc Calculator) Add(a, b float64) float64 {
return a + b
}
func (calc Calculator) Subtract(a, b float64) float64 {
return a - b
}
func (calc Calculator) Multiply(a, b float64) float64 {
return a * b
}
func (calc Calculator) Divide(a, b float64) float64 {
if b != 0 {
return a / b
}
return 0
}
// 字符串构建器(链式调用)
type StringBuilder struct {
parts []string
}
func NewStringBuilder() *StringBuilder {
return &StringBuilder{parts: make([]string, 0)}
}
func (sb *StringBuilder) Append(str string) *StringBuilder {
sb.parts = append(sb.parts, str)
return sb
}
func (sb *StringBuilder) ToUpper() *StringBuilder {
for i, part := range sb.parts {
sb.parts[i] = strings.ToUpper(part)
}
return sb
}
func (sb *StringBuilder) Build() string {
return strings.Join(sb.parts, "")
}
/*
运行这个程序:
go run 05-methods.go
学习要点:
1. 方法是与特定类型关联的函数
2. 方法定义语法func (receiver Type) MethodName() ReturnType
3. 值接收者和指针接收者有不同的行为和用途
4. 方法集决定了类型可以实现哪些接口
5. 结构体嵌入可以实现方法的继承和组合
方法 vs 函数:
1. 方法有接收者,函数没有
2. 方法属于特定类型,函数是独立的
3. 方法可以访问接收者的字段和其他方法
4. 方法支持多态(通过接口)
接收者类型选择:
1. 值接收者:
- 不需要修改接收者
- 接收者是小的结构体
- 接收者是基本类型、数组或小的结构体
2. 指针接收者:
- 需要修改接收者
- 接收者是大的结构体(避免拷贝)
- 接收者包含不能拷贝的字段(如 sync.Mutex
方法集规则:
1. 值类型 T 的方法集:所有值接收者方法
2. 指针类型 *T 的方法集:所有值接收者和指针接收者方法
3. 接口实现需要考虑方法集的匹配
最佳实践:
1. 保持接收者类型的一致性
2. 优先使用指针接收者(除非有特殊原因)
3. 合理使用结构体嵌入实现代码复用
4. 设计清晰的接口和方法签名
5. 使用方法实现面向对象的设计模式
常见应用场景:
1. 数据封装和操作
2. 业务逻辑实现
3. 接口实现和多态
4. 链式调用和流畅接口
5. 状态管理
6. 配置和选项处理
高级特性:
1. 方法表达式和方法值
2. 接口组合
3. 类型断言
4. 动态方法调用
5. 链式方法调用
*/

View File

@@ -0,0 +1,16 @@
# 第三章:函数和方法
本章将学习 Go 语言的函数定义、调用以及方法的概念。
## 学习目标
- 掌握函数的定义和调用
- 理解多返回值的概念
- 学会使用可变参数
- 了解闭包和方法
## 文件列表
- `01-basic-functions.go` - 基础函数
- `02-multiple-returns.go` - 多返回值
- `03-variadic-functions.go` - 可变参数函数
- `04-closures.go` - 闭包
- `05-methods.go` - 方法