Add Chapter 4: Functions and Interfaces - Closures, Defer, Panic/Recover, and Interfaces (Deep Dive)
This commit is contained in:
429
chapters/chapter-4/main.go
Normal file
429
chapters/chapter-4/main.go
Normal file
@@ -0,0 +1,429 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 4.1 函数基础
|
||||
func add(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
|
||||
func divide(a, b float64) (float64, error) {
|
||||
if b == 0 {
|
||||
return 0, fmt.Errorf("除数不能为零")
|
||||
}
|
||||
return a / b, nil
|
||||
}
|
||||
|
||||
func divideNamed(a, b float64) (result float64, err error) {
|
||||
if b == 0 {
|
||||
err = fmt.Errorf("除数不能为零")
|
||||
return
|
||||
}
|
||||
result = a / b
|
||||
return
|
||||
}
|
||||
|
||||
func sum(nums ...int) int {
|
||||
total := 0
|
||||
for _, n := range nums {
|
||||
total += n
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
func functionBasics() {
|
||||
fmt.Println("=== 函数基础 ===")
|
||||
fmt.Println("add(3, 4):", add(3, 4))
|
||||
|
||||
result, err := divide(10, 2)
|
||||
if err != nil {
|
||||
fmt.Println("错误:", err)
|
||||
} else {
|
||||
fmt.Printf("10 / 2 = %.2f\n", result)
|
||||
}
|
||||
|
||||
result2, _ := divideNamed(20, 4)
|
||||
fmt.Printf("20 / 4 = %.2f\n", result2)
|
||||
|
||||
fmt.Println("sum(1,2,3,4,5):", sum(1, 2, 3, 4, 5))
|
||||
nums := []int{10, 20, 30}
|
||||
fmt.Println("sum(nums...):", sum(nums...))
|
||||
}
|
||||
|
||||
// 4.2 闭包
|
||||
func createCounter() func() int {
|
||||
count := 0
|
||||
return func() int {
|
||||
count++
|
||||
return count
|
||||
}
|
||||
}
|
||||
|
||||
func createMultiplier(factor int) func(int) int {
|
||||
return func(x int) int {
|
||||
return x * factor
|
||||
}
|
||||
}
|
||||
|
||||
func closureLoopBug() {
|
||||
funcs := make([]func(), 3)
|
||||
for i := 0; i < 3; i++ {
|
||||
funcs[i] = func() {
|
||||
fmt.Print(i, " ")
|
||||
}
|
||||
}
|
||||
fmt.Print("Bug: ")
|
||||
for _, f := range funcs {
|
||||
f()
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func closureLoopFix() {
|
||||
funcs := make([]func(), 3)
|
||||
for i := 0; i < 3; i++ {
|
||||
i := i
|
||||
funcs[i] = func() {
|
||||
fmt.Print(i, " ")
|
||||
}
|
||||
}
|
||||
fmt.Print("Fix: ")
|
||||
for _, f := range funcs {
|
||||
f()
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func closureDemo() {
|
||||
fmt.Println("\n=== 闭包示例 ===")
|
||||
|
||||
counter := createCounter()
|
||||
fmt.Println("counter():", counter()) // 1
|
||||
fmt.Println("counter():", counter()) // 2
|
||||
fmt.Println("counter():", counter()) // 3
|
||||
|
||||
double := createMultiplier(2)
|
||||
triple := createMultiplier(3)
|
||||
fmt.Println("double(5):", double(5)) // 10
|
||||
fmt.Println("triple(5):", triple(5)) // 15
|
||||
|
||||
closureLoopBug()
|
||||
closureLoopFix()
|
||||
}
|
||||
|
||||
// 4.3 defer
|
||||
func deferDemo() {
|
||||
fmt.Println("\n=== defer 示例 ===")
|
||||
|
||||
defer fmt.Println("延迟 1")
|
||||
defer fmt.Println("延迟 2")
|
||||
fmt.Println("立即执行")
|
||||
|
||||
// defer 参数求值
|
||||
i := 0
|
||||
defer fmt.Println("defer 时求值 i =", i)
|
||||
i = 10
|
||||
|
||||
// 闭包 defer
|
||||
defer func() {
|
||||
fmt.Println("执行时求值 i =", i)
|
||||
}()
|
||||
|
||||
fmt.Println("defer 结束")
|
||||
}
|
||||
|
||||
func deferLoopDemo() {
|
||||
fmt.Println("\n=== defer 循环陷阱 ===")
|
||||
|
||||
// 错误:循环中 defer
|
||||
for i := 0; i < 3; i++ {
|
||||
f, err := os.Create(fmt.Sprintf("temp%d.txt", i))
|
||||
if err != nil {
|
||||
fmt.Println("创建文件失败:", err)
|
||||
continue
|
||||
}
|
||||
defer f.Close() // 所有 defer 在函数结束时执行
|
||||
f.WriteString("test")
|
||||
}
|
||||
|
||||
// 正确:立即执行
|
||||
for i := 0; i < 3; i++ {
|
||||
func() {
|
||||
f, err := os.Create(fmt.Sprintf("temp2_%d.txt", i))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
f.WriteString("test")
|
||||
}()
|
||||
}
|
||||
|
||||
fmt.Println("文件操作完成")
|
||||
}
|
||||
|
||||
// 4.4 panic 和 recover
|
||||
func panicDemo() {
|
||||
fmt.Println("\n=== panic 和 recover ===")
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("捕获 panic:", r)
|
||||
}
|
||||
}()
|
||||
|
||||
fmt.Println("开始")
|
||||
panic("发生错误")
|
||||
fmt.Println("不会执行")
|
||||
}
|
||||
|
||||
type MyError struct {
|
||||
Code int
|
||||
Message string
|
||||
}
|
||||
|
||||
func (e MyError) Error() string {
|
||||
return fmt.Sprintf("错误码 %d: %s", e.Code, e.Message)
|
||||
}
|
||||
|
||||
func safeDivide(a, b int) int {
|
||||
if b == 0 {
|
||||
panic(MyError{Code: 1001, Message: "除数不能为零"})
|
||||
}
|
||||
return a / b
|
||||
}
|
||||
|
||||
func handlePanic() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if err, ok := r.(MyError); ok {
|
||||
fmt.Printf("自定义错误:代码=%d, 消息=%s\n", err.Code, err.Message)
|
||||
} else {
|
||||
fmt.Printf("未知 panic: %v\n", r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
safeDivide(10, 0)
|
||||
}
|
||||
|
||||
func panicRecoverDemo() {
|
||||
panicDemo()
|
||||
handlePanic()
|
||||
}
|
||||
|
||||
// 4.5 接口
|
||||
type Speaker interface {
|
||||
Speak() string
|
||||
}
|
||||
|
||||
type Dog struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (d Dog) Speak() string {
|
||||
return d.Name + " 汪汪叫"
|
||||
}
|
||||
|
||||
type Cat struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (c Cat) Speak() string {
|
||||
return c.Name + " 喵喵叫"
|
||||
}
|
||||
|
||||
func makeSound(s Speaker) {
|
||||
fmt.Println(s.Speak())
|
||||
}
|
||||
|
||||
func typeAssertionDemo() {
|
||||
fmt.Println("\n=== 类型断言 ===")
|
||||
|
||||
var v interface{} = "hello"
|
||||
|
||||
// 基本断言
|
||||
if s, ok := v.(string); ok {
|
||||
fmt.Println("是字符串:", s)
|
||||
}
|
||||
|
||||
// 类型开关
|
||||
switch t := v.(type) {
|
||||
case int:
|
||||
fmt.Printf("整数:%d\n", t)
|
||||
case string:
|
||||
fmt.Printf("字符串:%s\n", t)
|
||||
default:
|
||||
fmt.Printf("未知类型:%T\n", t)
|
||||
}
|
||||
}
|
||||
|
||||
func interfaceDemo() {
|
||||
dog := Dog{Name: "旺财"}
|
||||
cat := Cat{Name: "咪咪"}
|
||||
|
||||
makeSound(dog)
|
||||
makeSound(cat)
|
||||
|
||||
typeAssertionDemo()
|
||||
}
|
||||
|
||||
// 4.6 综合案例:插件系统
|
||||
type Plugin interface {
|
||||
Name() string
|
||||
Run() error
|
||||
}
|
||||
|
||||
type HelloPlugin struct{}
|
||||
|
||||
func (h HelloPlugin) Name() string {
|
||||
return "HelloPlugin"
|
||||
}
|
||||
|
||||
func (h HelloPlugin) Run() error {
|
||||
fmt.Println("Hello from plugin!")
|
||||
return nil
|
||||
}
|
||||
|
||||
type MathPlugin struct{}
|
||||
|
||||
func (m MathPlugin) Name() string {
|
||||
return "MathPlugin"
|
||||
}
|
||||
|
||||
func (m MathPlugin) Run() error {
|
||||
fmt.Printf("2 + 2 = %d\n", 2+2)
|
||||
return nil
|
||||
}
|
||||
|
||||
func pluginDemo() {
|
||||
fmt.Println("\n=== 插件系统 ===")
|
||||
|
||||
plugins := []Plugin{
|
||||
HelloPlugin{},
|
||||
MathPlugin{},
|
||||
}
|
||||
|
||||
for _, p := range plugins {
|
||||
fmt.Printf("加载插件:%s\n", p.Name())
|
||||
if err := p.Run(); err != nil {
|
||||
fmt.Println("插件运行失败:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4.6 综合案例:中间件链
|
||||
type Middleware func(Handler) Handler
|
||||
type Handler func(string) string
|
||||
|
||||
func logging(next Handler) Handler {
|
||||
return func(input string) string {
|
||||
fmt.Printf("[LOG] 输入:%s\n", input)
|
||||
result := next(input)
|
||||
fmt.Printf("[LOG] 输出:%s\n", result)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
func timing(next Handler) Handler {
|
||||
return func(input string) string {
|
||||
start := time.Now()
|
||||
result := next(input)
|
||||
fmt.Printf("[TIME] 耗时:%v\n", time.Since(start))
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
func auth(next Handler) Handler {
|
||||
return func(input string) string {
|
||||
if input == "" {
|
||||
return "错误:空输入"
|
||||
}
|
||||
return next(input)
|
||||
}
|
||||
}
|
||||
|
||||
func businessLogic(input string) string {
|
||||
return "处理结果:" + input
|
||||
}
|
||||
|
||||
func middlewareDemo() {
|
||||
fmt.Println("\n=== 中间件链 ===")
|
||||
|
||||
handler := auth(timing(logging(businessLogic)))
|
||||
result := handler("测试数据")
|
||||
fmt.Println("最终结果:", result)
|
||||
}
|
||||
|
||||
// 4.6 综合案例:错误包装
|
||||
type AppError struct {
|
||||
Code int
|
||||
Message string
|
||||
Cause error
|
||||
}
|
||||
|
||||
func (e *AppError) Error() string {
|
||||
if e.Cause != nil {
|
||||
return fmt.Sprintf("错误码 %d: %s (原因:%v)", e.Code, e.Message, e.Cause)
|
||||
}
|
||||
return fmt.Sprintf("错误码 %d: %s", e.Code, e.Message)
|
||||
}
|
||||
|
||||
func wrapError(err error, code int, message string) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &AppError{
|
||||
Code: code,
|
||||
Message: message,
|
||||
Cause: err,
|
||||
}
|
||||
}
|
||||
|
||||
func readFile(path string) ([]byte, error) {
|
||||
return nil, fmt.Errorf("文件不存在")
|
||||
}
|
||||
|
||||
func processFile(path string) error {
|
||||
data, err := readFile(path)
|
||||
if err != nil {
|
||||
return wrapError(err, 1001, "读取文件失败")
|
||||
}
|
||||
|
||||
if len(data) == 0 {
|
||||
return wrapError(nil, 1002, "文件为空")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func errorHandlingDemo() {
|
||||
fmt.Println("\n=== 错误处理链 ===")
|
||||
|
||||
err := processFile("test.txt")
|
||||
if err != nil {
|
||||
if appErr, ok := err.(*AppError); ok {
|
||||
fmt.Printf("应用错误:代码=%d, 消息=%s\n", appErr.Code, appErr.Message)
|
||||
if appErr.Cause != nil {
|
||||
fmt.Printf("根本原因:%v\n", appErr.Cause)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("未知错误:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
functionBasics()
|
||||
closureDemo()
|
||||
deferDemo()
|
||||
deferLoopDemo()
|
||||
panicRecoverDemo()
|
||||
interfaceDemo()
|
||||
pluginDemo()
|
||||
middlewareDemo()
|
||||
errorHandlingDemo()
|
||||
}
|
||||
Reference in New Issue
Block a user