430 lines
7.4 KiB
Go
430 lines
7.4 KiB
Go
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()
|
|
}
|