This commit is contained in:
2026-03-13 23:54:07 +08:00
parent 9c065bcae4
commit d0f8c44411
45 changed files with 3439 additions and 1 deletions
@@ -0,0 +1,94 @@
# 01-basic-functions - 基础函数
## 知识点讲解
### 函数基本语法
```go
func 函数名(参数列表) 返回值类型 {
// 函数体
}
```
### 无参数无返回值
```go
func greet() {
fmt.Println("Hello, World!")
}
```
### 有参数无返回值
```go
func greet(name string) {
fmt.Printf("Hello, %s!\n", name)
}
```
### 单返回值
```go
func add(a, b int) int {
return a + b
}
```
### 多参数
```go
func multiply(a, b, c int) int {
return a * b * c
}
```
### 可变参数
```go
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
```
**调用**:
```go
sum(1, 2, 3) // 直接传参
nums := []int{1, 2, 3}
sum(nums...) // 解包切片
```
### 命名返回值
```go
func divide(a, b int) (result int, err error) {
if b == 0 {
err = fmt.Errorf("division by zero")
return
}
result = a / b
return
}
```
### 重要提示
- Go函数可以有多个返回值,这是Go的特色
- 函数的参数和返回值都是按值传递(值传递)
- 可变参数必须是函数的最后一个参数
- 命名返回值可以让代码更清晰
## 学习目标
完成本练习后,你将:
- ✅ 掌握函数的基本定义方式
- ✅ 理解参数传递机制
- ✅ 学会使用可变参数
- ✅ 了解命名返回值的用法
## 练习说明
打开 `main.go`,根据注释提示填充代码,完成后运行 `go test -v` 验证答案。
@@ -0,0 +1,87 @@
package main
import "fmt"
func exercise1() int {
fmt.Println("=== 练习1:无参数单返回值函数 ===")
// 定义一个函数square,接收一个int参数,返回其平方
// 定义一个函数cube,接收一个int参数,返回其立方
// 调用这两个函数并返回它们的和
____ func ____
square := func(n int) ____ { return n * n }
____
}
cube := func(n int) ____ { ____ }
return ____(3) + ____(2)
}
func exercise2(a, b int) {
fmt.Println("\n=== 练习2:多个参数 ===")
// 定义一个函数,接收两个int参数a和b
// 打印a + b, a - b, a * b
// 格式: "加: 5, 减: 1, 乘: 6"
fmt.Printf("加: %d, 减: %d, 乘: %d\n", ____, ____, ____)
}
func exercise3(nums ...int) int {
fmt.Println("\n=== 练习3:可变参数 ===")
// 定义一个可变参数函数,计算所有数字的和
sum := ____
for _, num := range ____ {
____
}
return ____
}
func exercise4(name, city string) (string, string) {
fmt.Println("\n=== 练习4:命名返回值 ===")
// 使用命名返回值,返回两个字符串
// nameWithGreeting: 格式为 "Hello, {name}"
// info: 格式为 "{name} lives in {city}"
var ____ string
var ____
nameWithGreeting = fmt.Sprintf("Hello, %s", name)
info = fmt.Sprintf("%s lives in %s", name, city)
return ____, ____
}
func exercise5(name string) string {
fmt.Println("\n=== 练习5:匿名函数 ===")
// 使用匿名函数,对name进行处理
// 返回大写的name
// 提示:使用strings.ToUpper
____ := ____
return ____
}
func main() {
fmt.Println("=== 基础函数 练习 ===\n")
result1 := exercise1()
fmt.Printf("练习1结果: %d\n", result1)
exercise2(3, 2)
result3 := exercise3(1, 2, 3, 4, 5)
fmt.Printf("练习3结果: %d\n", result3)
s4, i4 := exercise4("张三", "北京")
fmt.Printf("练习4结果: %s, %s\n", s4, i4)
result5 := exercise5("hello world")
fmt.Printf("练习5结果: %s\n", result5)
}
@@ -0,0 +1,80 @@
package main
import (
"bytes"
"os"
"strings"
"testing"
)
func captureOutput(f func()) string {
old := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
f()
w.Close()
os.Stdout = old
var buf bytes.Buffer
buf.ReadFrom(r)
return buf.String()
}
func TestExercise1(t *testing.T) {
result := exercise1()
if result != 17 {
t.Errorf("期望结果 17, 实际: %d", result)
}
}
func TestExercise2(t *testing.T) {
output := captureOutput(func() { exercise2(3, 2) })
if !strings.Contains(output, "加: 5, 减: 1, 乘: 6") {
t.Error("期望输出 '加: 5, 减: 1, 乘: 6'")
}
}
func TestExercise3(t *testing.T) {
result := exercise3(1, 2, 3, 4, 5)
if result != 15 {
t.Errorf("期望结果 15, 实际: %d", result)
}
}
func TestExercise4(t *testing.T) {
s4, i4 := exercise4("张三", "北京")
if s4 != "Hello, 张三" {
t.Errorf("期望 'Hello, 张三', 实际: %s", s4)
}
if i4 != "张三 lives in 北京" {
t.Errorf("期望 '张三 lives in 北京', 实际: %s", i4)
}
}
func TestExercise5(t *testing.T) {
result := exercise5("hello world")
if result != "HELLO WORLD" {
t.Errorf("期望 'HELLO WORLD', 实际: %s", result)
}
}
func TestMainFunction(t *testing.T) {
output := captureOutput(main)
requiredSections := []string{
"=== 基础函数 练习 ===",
"练习1:无参数单返回值函数",
"练习2:多个参数",
"练习3:可变参数",
"练习4:命名返回值",
"练习5:匿名函数",
}
for _, section := range requiredSections {
if !strings.Contains(output, section) {
t.Errorf("期望输出包含 '%s'", section)
}
}
}
@@ -0,0 +1,56 @@
# 02-multiple-returns - 多返回值
## 知识点讲解
多返回值是Go语言的特色功能之一。
### 多返回值语法
```go
func divide(a, b int) (int, error) {
if b == 0 {
return 0, fmt.Errorf("division by zero")
}
return a / b, nil
}
```
### 接收返回值
```go
result, err := divide(10, 2)
if err != nil {
// 处理错误
}
```
### 忽略返回值
使用`_`忽略不需要的返回值:
```go
result, _ := divide(10, 2) // 忽略错误
_, err := divide(10, 0) // 只关心错误
```
### 命名返回值
```go
func rectangle(width, height int) (area, perimeter int) {
area = width * height
perimeter = 2 * (width + height)
return // 此时return会返回所有命名返回值
}
```
## 学习目标
完成本练习后,你将:
- ✅ 掌握多返回值的定义和使用
- ✅ 学会忽略不需要的返回值
- ✅ 理解命名的多返回值
- ✅ 掌握错误处理的模式
## 练习说明
打开 `main.go`,根据注释提示填充代码,完成后运行 `go test -v` 验证答案。
@@ -0,0 +1,42 @@
package main
import (
"errors"
"fmt"
"time"
)
func exercise1(x, y int) (int, int) {
// 返回x+y和x-y
return ____, ____
}
func exercise2(n int) (int, error) {
// 如果n<0,返回0和错误
// 否则返回n和nil
if ____ {
return ____, ____
}
return ____, ____
}
func exercise3(s string) (bool, int) {
// 返回字符串是否包含"hello"和字符串长度
contains := true
length := ____
return ____, ____
}
func main() {
fmt.Println("=== 多返回值 练习 ===\n")
sum, diff := exercise1(10, 3)
fmt.Printf("练习1: 加=%d, 减=%d\n", ____, ____)
result, err := exercise2(-5)
if ____ {
fmt.Printf("练习2: 错误 = %v\n", ____)
} else {
fmt.Printf("练习2: 结果 = %d\n", ____)
}
}
@@ -0,0 +1,19 @@
package main
import (
"testing"
)
func TestExercise1(t *testing.T) {
sum, diff := exercise1(10, 3)
if sum != 13 || diff != 7 {
t.Errorf("期望 sum=13, diff=7, 实际 sum=%d, diff=%d", sum, diff)
}
}
func TestExercise2(t *testing.T) {
_, err := exercise2(-5)
if err == nil {
t.Error("期望返回错误,但返回了nil")
}
}
+20
View File
@@ -0,0 +1,20 @@
# 03-closures - 闭包
闭包是指能够访问其定义作用域外变量的函数。
## 知识点讲解
```go
func makeAdder(x int) func(int) int {
return func(y int) int {
return x + y // 访问外部变量x
}
}
add5 := makeAdder(5)
result := add5(3) // 返回8
```
## 练习说明
打开 `main.go`,根据注释提示填充代码,完成后运行 `go test -v` 验证答案。
@@ -0,0 +1,7 @@
# 04-higher-order - 高阶函数
函数作为参数和返回值。
## 练习说明
打开 `main.go`,根据注释提示填充代码,完成后运行 `go test -v` 验证答案。
+28
View File
@@ -0,0 +1,28 @@
# Stage 03 - 函数
学习Go语言的函数特性,包括多返回值、闭包和高阶函数。
## 学习目标
完成本阶段后,你将掌握:
- ✅ 函数定义与调用
- ✅ 多返回值(Go的特色)
- ✅ 闭包函数
- ✅ 高阶函数(函数作为参数和返回值)
## 练习列表
1. **01-basic-functions** - 基础函数
2. **02-multiple-returns** - 多返回值
3. **03-closures** - 闭包
4. **04-higher-order** - 高阶函数
## 预计用时
每练习15-20分钟,本阶段约1-1.5小时
## 备注
- 支持命名返回值
- 支持可变参数
- 函数是Go的一等公民