Files
golang/golang-learning/03-functions/01-basic-functions.go
2025-08-24 01:01:26 +08:00

722 lines
16 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
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. 工具函数库
*/