1 IO流

1.1 分类

01.Go的IO分类
    a.按接口划分
        Reader接口:定义读取操作
        Writer接口:定义写入操作
        Closer接口:定义关闭操作
        Seeker接口:定义定位操作
    b.按功能划分
        文件IO:os包提供文件操作
        缓冲IO:bufio包提供缓冲功能
        内存IO:bytes和strings包提供内存操作
        网络IO:net包提供网络操作
        格式化IO:fmt包提供格式化读写

02.核心接口
    a.io.Reader接口
        定义:读取数据的基本接口
        方法:Read(p []byte) (n int, err error)
        返回:读取的字节数和错误信息
    b.io.Writer接口
        定义:写入数据的基本接口
        方法:Write(p []byte) (n int, err error)
        返回:写入的字节数和错误信息
    c.io.Closer接口
        定义:关闭资源的接口
        方法:Close() error
        作用:释放资源,防止泄漏

1.2 Reader接口

01.Reader接口定义
    a.基本定义
        Reader接口是Go中所有读取操作的基础接口
    b.接口方法
        ---
        type Reader interface {
            Read(p []byte) (n int, err error)
        }
        ---
    c.方法说明
        Read方法从数据源读取最多len(p)字节到p中
        返回读取的字节数n和遇到的错误err
        当读取到文件末尾时返回io.EOF错误

02.常用Reader实现
    a.os.File
        文件读取器,实现了Reader接口
    b.strings.Reader
        字符串读取器,从字符串读取数据
    c.bytes.Reader
        字节切片读取器,从字节切片读取数据
    d.bufio.Reader
        缓冲读取器,提供缓冲功能提高性能

03.Reader使用示例
    a.基本读取
        ---
        package main

        import (
            "fmt"
            "io"
            "strings"
        )

        func main() {
            // 创建字符串读取器
            reader := strings.NewReader("Hello, Go!")

            // 创建缓冲区
            buf := make([]byte, 5)

            // 循环读取
            for {
                n, err := reader.Read(buf)
                if err == io.EOF {
                    break
                }
                if err != nil {
                    fmt.Println("读取错误:", err)
                    return
                }
                fmt.Printf("读取%d字节: %s\n", n, buf[:n])
            }
        }
        ---
    b.一次性读取全部
        ---
        package main

        import (
            "fmt"
            "io"
            "strings"
        )

        func main() {
            reader := strings.NewReader("Hello, Go!")

            // 使用io.ReadAll一次性读取全部内容
            data, err := io.ReadAll(reader)
            if err != nil {
                fmt.Println("读取错误:", err)
                return
            }
            fmt.Println("读取内容:", string(data))
        }
        ---

1.3 Writer接口

01.Writer接口定义
    a.基本定义
        Writer接口是Go中所有写入操作的基础接口
    b.接口方法
        ---
        type Writer interface {
            Write(p []byte) (n int, err error)
        }
        ---
    c.方法说明
        Write方法将p中的数据写入到底层数据流
        返回写入的字节数n和遇到的错误err
        当n < len(p)时必须返回非nil的错误

02.常用Writer实现
    a.os.File
        文件写入器,实现了Writer接口
    b.bytes.Buffer
        字节缓冲区,可以写入数据到内存
    c.bufio.Writer
        缓冲写入器,提供缓冲功能提高性能
    d.os.Stdout
        标准输出,写入到控制台

03.Writer使用示例
    a.基本写入
        ---
        package main

        import (
            "fmt"
            "os"
        )

        func main() {
            // 创建文件
            file, err := os.Create("output.txt")
            if err != nil {
                fmt.Println("创建文件错误:", err)
                return
            }
            defer file.Close()

            // 写入数据
            data := []byte("Hello, Go!")
            n, err := file.Write(data)
            if err != nil {
                fmt.Println("写入错误:", err)
                return
            }
            fmt.Printf("写入%d字节\n", n)
        }
        ---
    b.使用bytes.Buffer
        ---
        package main

        import (
            "bytes"
            "fmt"
        )

        func main() {
            var buf bytes.Buffer

            // 写入数据到缓冲区
            buf.Write([]byte("Hello, "))
            buf.WriteString("Go!")

            // 读取缓冲区内容
            fmt.Println(buf.String())
        }
        ---

1.4 文件操作:os包

01.文件打开与创建
    a.os.Open
        功能:以只读模式打开文件
        ---
        file, err := os.Open("test.txt")
        if err != nil {
            log.Fatal(err)
        }
        defer file.Close()
        ---
    b.os.Create
        功能:创建或截断文件
        ---
        file, err := os.Create("output.txt")
        if err != nil {
            log.Fatal(err)
        }
        defer file.Close()
        ---
    c.os.OpenFile
        功能:以指定模式打开文件
        ---
        file, err := os.OpenFile("test.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
        if err != nil {
            log.Fatal(err)
        }
        defer file.Close()
        ---

02.文件读取
    a.Read方法
        功能:读取指定字节数
        ---
        buf := make([]byte, 1024)
        n, err := file.Read(buf)
        if err != nil && err != io.EOF {
            log.Fatal(err)
        }
        fmt.Printf("读取%d字节: %s\n", n, buf[:n])
        ---
    b.ReadAt方法
        功能:从指定位置读取
        ---
        buf := make([]byte, 10)
        n, err := file.ReadAt(buf, 5)
        if err != nil && err != io.EOF {
            log.Fatal(err)
        }
        fmt.Printf("从位置5读取%d字节\n", n)
        ---

03.文件写入
    a.Write方法
        功能:写入字节切片
        ---
        data := []byte("Hello, Go!")
        n, err := file.Write(data)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("写入%d字节\n", n)
        ---
    b.WriteString方法
        功能:写入字符串
        ---
        n, err := file.WriteString("Hello, Go!")
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("写入%d字节\n", n)
        ---

04.文件信息与操作
    a.Stat获取文件信息
        ---
        fileInfo, err := file.Stat()
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println("文件名:", fileInfo.Name())
        fmt.Println("文件大小:", fileInfo.Size())
        fmt.Println("修改时间:", fileInfo.ModTime())
        fmt.Println("是否目录:", fileInfo.IsDir())
        ---
    b.文件删除
        ---
        err := os.Remove("test.txt")
        if err != nil {
            log.Fatal(err)
        }
        ---
    c.文件重命名
        ---
        err := os.Rename("old.txt", "new.txt")
        if err != nil {
            log.Fatal(err)
        }
        ---

05.目录操作
    a.创建目录
        ---
        // 创建单级目录
        err := os.Mkdir("testdir", 0755)

        // 创建多级目录
        err := os.MkdirAll("path/to/dir", 0755)
        ---
    b.读取目录
        ---
        entries, err := os.ReadDir(".")
        if err != nil {
            log.Fatal(err)
        }
        for _, entry := range entries {
            fmt.Println(entry.Name(), entry.IsDir())
        }
        ---
    c.删除目录
        ---
        // 删除空目录
        err := os.Remove("testdir")

        // 删除目录及其内容
        err := os.RemoveAll("testdir")
        ---

1.5 缓冲IO:bufio包

01.bufio.Reader
    a.创建缓冲读取器
        ---
        file, _ := os.Open("test.txt")
        reader := bufio.NewReader(file)
        ---
    b.按行读取
        ---
        package main

        import (
            "bufio"
            "fmt"
            "os"
        )

        func main() {
            file, err := os.Open("test.txt")
            if err != nil {
                fmt.Println("打开文件错误:", err)
                return
            }
            defer file.Close()

            scanner := bufio.NewScanner(file)
            for scanner.Scan() {
                fmt.Println(scanner.Text())
            }

            if err := scanner.Err(); err != nil {
                fmt.Println("读取错误:", err)
            }
        }
        ---
    c.ReadString方法
        ---
        reader := bufio.NewReader(os.Stdin)
        fmt.Print("请输入: ")
        input, err := reader.ReadString('\n')
        if err != nil {
            fmt.Println("读取错误:", err)
            return
        }
        fmt.Println("你输入了:", input)
        ---

02.bufio.Writer
    a.创建缓冲写入器
        ---
        file, _ := os.Create("output.txt")
        writer := bufio.NewWriter(file)
        defer writer.Flush() // 刷新缓冲区
        ---
    b.写入数据
        ---
        package main

        import (
            "bufio"
            "fmt"
            "os"
        )

        func main() {
            file, err := os.Create("output.txt")
            if err != nil {
                fmt.Println("创建文件错误:", err)
                return
            }
            defer file.Close()

            writer := bufio.NewWriter(file)

            // 写入数据
            writer.WriteString("Hello, ")
            writer.WriteString("Go!\n")

            // 刷新缓冲区,确保数据写入文件
            writer.Flush()
        }
        ---

03.性能优势
    a.减少系统调用
        bufio通过缓冲区减少了对底层IO的系统调用次数
    b.提高读写效率
        批量读写数据,提高IO性能
    c.适用场景
        频繁的小数据读写操作
        按行处理文本文件
        网络数据传输

1.6 内存IO:bytes和strings

01.bytes.Buffer
    a.创建Buffer
        ---
        var buf bytes.Buffer
        // 或
        buf := new(bytes.Buffer)
        // 或
        buf := bytes.NewBuffer([]byte("initial data"))
        ---
    b.写入操作
        ---
        package main

        import (
            "bytes"
            "fmt"
        )

        func main() {
            var buf bytes.Buffer

            // 写入字节
            buf.Write([]byte("Hello, "))

            // 写入字符串
            buf.WriteString("Go!")

            // 写入单个字节
            buf.WriteByte('!')

            // 写入rune
            buf.WriteRune('中')

            fmt.Println(buf.String())
        }
        ---
    c.读取操作
        ---
        buf := bytes.NewBufferString("Hello, Go!")

        // 读取所有数据
        data := buf.Bytes()

        // 读取字符串
        str := buf.String()

        // 读取指定字节数
        p := make([]byte, 5)
        n, _ := buf.Read(p)
        fmt.Printf("读取%d字节: %s\n", n, p)
        ---

02.bytes包常用函数
    a.字节切片比较
        ---
        a := []byte("hello")
        b := []byte("hello")

        // 比较是否相等
        equal := bytes.Equal(a, b)

        // 比较大小
        cmp := bytes.Compare(a, b) // 返回-1, 0, 1
        ---
    b.字节切片查找
        ---
        data := []byte("Hello, Go!")

        // 查找子切片
        index := bytes.Index(data, []byte("Go"))

        // 判断是否包含
        contains := bytes.Contains(data, []byte("Go"))

        // 统计出现次数
        count := bytes.Count(data, []byte("o"))
        ---
    c.字节切片分割
        ---
        data := []byte("a,b,c,d")

        // 按分隔符分割
        parts := bytes.Split(data, []byte(","))

        // 分割为n部分
        parts := bytes.SplitN(data, []byte(","), 2)
        ---

03.strings.Reader
    a.创建字符串读取器
        ---
        reader := strings.NewReader("Hello, Go!")
        ---
    b.读取操作
        ---
        package main

        import (
            "fmt"
            "io"
            "strings"
        )

        func main() {
            reader := strings.NewReader("Hello, Go!")

            // 读取数据
            buf := make([]byte, 5)
            for {
                n, err := reader.Read(buf)
                if err == io.EOF {
                    break
                }
                fmt.Printf("%s", buf[:n])
            }
        }
        ---
    c.定位操作
        ---
        reader := strings.NewReader("Hello, Go!")

        // 移动到指定位置
        reader.Seek(7, io.SeekStart)

        // 读取剩余内容
        data, _ := io.ReadAll(reader)
        fmt.Println(string(data)) // 输出: Go!
        ---

04.strings包常用函数
    a.字符串查找
        ---
        str := "Hello, Go!"

        // 查找子串
        index := strings.Index(str, "Go")

        // 判断是否包含
        contains := strings.Contains(str, "Go")

        // 统计出现次数
        count := strings.Count(str, "o")
        ---
    b.字符串分割与连接
        ---
        // 分割字符串
        parts := strings.Split("a,b,c", ",")

        // 连接字符串
        joined := strings.Join([]string{"a", "b", "c"}, ",")
        ---
    c.字符串替换
        ---
        str := "Hello, Go!"

        // 替换所有匹配
        newStr := strings.ReplaceAll(str, "o", "0")

        // 替换n次
        newStr := strings.Replace(str, "o", "0", 1)
        ---

1.7 格式化IO:fmt包

01.格式化输出
    a.Print系列
        ---
        fmt.Print("Hello")        // 输出不换行
        fmt.Println("Hello")      // 输出并换行
        fmt.Printf("Hello %s\n", "Go") // 格式化输出
        ---
    b.Sprint系列
        ---
        str := fmt.Sprint("Hello")
        str := fmt.Sprintln("Hello")
        str := fmt.Sprintf("Hello %s", "Go")
        ---
    c.Fprint系列
        ---
        file, _ := os.Create("output.txt")
        fmt.Fprint(file, "Hello")
        fmt.Fprintln(file, "Hello")
        fmt.Fprintf(file, "Hello %s\n", "Go")
        ---

02.格式化占位符
    a.通用占位符
        %v:默认格式
        %+v:带字段名的结构体
        %#v:Go语法表示
        %T:类型
        %%:百分号
    b.布尔值
        %t:true或false
    c.整数
        %d:十进制
        %b:二进制
        %o:八进制
        %x:十六进制小写
        %X:十六进制大写
    d.浮点数
        %f:小数点格式
        %e:科学计数法小写
        %E:科学计数法大写
        %g:根据情况选择%e或%f
    e.字符串
        %s:字符串
        %q:带引号的字符串
        %x:十六进制编码

03.格式化输入
    a.Scan系列
        ---
        var name string
        var age int

        fmt.Print("请输入姓名和年龄: ")
        fmt.Scan(&name, &age)

        fmt.Printf("姓名: %s, 年龄: %d\n", name, age)
        ---
    b.Scanf格式化输入
        ---
        var name string
        var age int

        fmt.Print("请输入(格式: name age): ")
        fmt.Scanf("%s %d", &name, &age)
        ---
    c.Scanln按行输入
        ---
        var input string
        fmt.Print("请输入: ")
        fmt.Scanln(&input)
        ---

04.实用示例
    a.格式化输出结构体
        ---
        package main

        import "fmt"

        type Person struct {
            Name string
            Age  int
        }

        func main() {
            p := Person{Name: "张三", Age: 25}

            fmt.Printf("%v\n", p)   // {张三 25}
            fmt.Printf("%+v\n", p)  // {Name:张三 Age:25}
            fmt.Printf("%#v\n", p)  // main.Person{Name:"张三", Age:25}
        }
        ---
    b.格式化数字
        ---
        num := 255

        fmt.Printf("十进制: %d\n", num)     // 255
        fmt.Printf("二进制: %b\n", num)     // 11111111
        fmt.Printf("八进制: %o\n", num)     // 377
        fmt.Printf("十六进制: %x\n", num)   // ff

        f := 3.14159
        fmt.Printf("浮点数: %.2f\n", f)     // 3.14
        ---

2 序列化

2.1 定义

01.序列化概念
    a.定义
        序列化是将数据结构或对象转换为可存储或传输的格式的过程
        反序列化是将序列化后的数据恢复为原始数据结构的过程
    b.用途
        数据持久化:将数据保存到文件或数据库
        网络传输:在网络中传输数据
        进程间通信:不同进程之间交换数据
    c.常见格式
        JSON:轻量级文本格式,易读易写
        XML:标记语言格式,结构化数据
        Gob:Go特有的二进制格式,高效
        Protocol Buffers:Google的二进制格式,跨语言

02.Go中的序列化
    a.encoding包
        Go标准库提供encoding包支持多种序列化格式
    b.常用子包
        encoding/json:JSON序列化
        encoding/xml:XML序列化
        encoding/gob:Gob序列化
        encoding/binary:二进制序列化

2.2 JSON序列化

01.JSON序列化基础
    a.Marshal序列化
        ---
        package main

        import (
            "encoding/json"
            "fmt"
        )

        type Person struct {
            Name string `json:"name"`
            Age  int    `json:"age"`
        }

        func main() {
            p := Person{Name: "张三", Age: 25}

            // 序列化为JSON
            data, err := json.Marshal(p)
            if err != nil {
                fmt.Println("序列化错误:", err)
                return
            }
            fmt.Println(string(data))
        }
        ---
    b.Unmarshal反序列化
        ---
        package main

        import (
            "encoding/json"
            "fmt"
        )

        type Person struct {
            Name string `json:"name"`
            Age  int    `json:"age"`
        }

        func main() {
            jsonStr := `{"name":"张三","age":25}`

            var p Person
            err := json.Unmarshal([]byte(jsonStr), &p)
            if err != nil {
                fmt.Println("反序列化错误:", err)
                return
            }
            fmt.Printf("%+v\n", p)
        }
        ---

02.JSON标签
    a.常用标签
        json:"name":指定JSON字段名
        json:"-":忽略该字段
        json:",omitempty":字段为空时忽略
        json:",string":将字段转为字符串
    b.标签示例
        ---
        type User struct {
            ID       int    `json:"id"`
            Name     string `json:"name"`
            Password string `json:"-"`              // 忽略
            Email    string `json:"email,omitempty"` // 空值忽略
            Age      int    `json:"age,string"`      // 转为字符串
        }
        ---

03.格式化JSON
    a.MarshalIndent格式化输出
        ---
        data, err := json.MarshalIndent(p, "", "  ")
        if err != nil {
            fmt.Println("序列化错误:", err)
            return
        }
        fmt.Println(string(data))
        ---
    b.Encoder和Decoder
        ---
        package main

        import (
            "encoding/json"
            "os"
        )

        type Person struct {
            Name string `json:"name"`
            Age  int    `json:"age"`
        }

        func main() {
            p := Person{Name: "张三", Age: 25}

            // 使用Encoder写入文件
            file, _ := os.Create("person.json")
            defer file.Close()

            encoder := json.NewEncoder(file)
            encoder.Encode(p)

            // 使用Decoder从文件读取
            file2, _ := os.Open("person.json")
            defer file2.Close()

            var p2 Person
            decoder := json.NewDecoder(file2)
            decoder.Decode(&p2)
        }
        ---

04.处理复杂类型
    a.嵌套结构体
        ---
        type Address struct {
            City    string `json:"city"`
            Country string `json:"country"`
        }

        type Person struct {
            Name    string  `json:"name"`
            Age     int     `json:"age"`
            Address Address `json:"address"`
        }
        ---
    b.切片和映射
        ---
        type Data struct {
            Tags  []string          `json:"tags"`
            Attrs map[string]string `json:"attrs"`
        }
        ---

2.3 XML序列化

01.XML序列化基础
    a.Marshal序列化
        ---
        package main

        import (
            "encoding/xml"
            "fmt"
        )

        type Person struct {
            XMLName xml.Name `xml:"person"`
            Name    string   `xml:"name"`
            Age     int      `xml:"age"`
        }

        func main() {
            p := Person{Name: "张三", Age: 25}

            data, err := xml.Marshal(p)
            if err != nil {
                fmt.Println("序列化错误:", err)
                return
            }
            fmt.Println(string(data))
        }
        ---
    b.Unmarshal反序列化
        ---
        xmlStr := `<person><name>张三</name><age>25</age></person>`

        var p Person
        err := xml.Unmarshal([]byte(xmlStr), &p)
        if err != nil {
            fmt.Println("反序列化错误:", err)
            return
        }
        fmt.Printf("%+v\n", p)
        ---

02.XML标签
    a.常用标签
        xml:"name":指定XML元素名
        xml:",attr":作为属性
        xml:",chardata":作为字符数据
        xml:",innerxml":保留原始XML
    b.标签示例
        ---
        type Book struct {
            XMLName xml.Name `xml:"book"`
            ID      int      `xml:"id,attr"`
            Title   string   `xml:"title"`
            Author  string   `xml:"author"`
            Content string   `xml:",chardata"`
        }
        ---

03.格式化XML
    a.MarshalIndent格式化输出
        ---
        data, err := xml.MarshalIndent(p, "", "  ")
        if err != nil {
            fmt.Println("序列化错误:", err)
            return
        }
        fmt.Println(xml.Header + string(data))
        ---

2.4 Gob序列化

01.Gob序列化基础
    a.特点
        Gob是Go特有的二进制序列化格式
        高效、紧凑,适合Go程序间通信
        不适合跨语言使用
    b.基本使用
        ---
        package main

        import (
            "bytes"
            "encoding/gob"
            "fmt"
        )

        type Person struct {
            Name string
            Age  int
        }

        func main() {
            p := Person{Name: "张三", Age: 25}

            // 序列化
            var buf bytes.Buffer
            encoder := gob.NewEncoder(&buf)
            err := encoder.Encode(p)
            if err != nil {
                fmt.Println("序列化错误:", err)
                return
            }

            // 反序列化
            var p2 Person
            decoder := gob.NewDecoder(&buf)
            err = decoder.Decode(&p2)
            if err != nil {
                fmt.Println("反序列化错误:", err)
                return
            }
            fmt.Printf("%+v\n", p2)
        }
        ---

02.Gob文件操作
    a.写入文件
        ---
        package main

        import (
            "encoding/gob"
            "os"
        )

        type Person struct {
            Name string
            Age  int
        }

        func main() {
            p := Person{Name: "张三", Age: 25}

            file, _ := os.Create("person.gob")
            defer file.Close()

            encoder := gob.NewEncoder(file)
            encoder.Encode(p)
        }
        ---
    b.从文件读取
        ---
        file, _ := os.Open("person.gob")
        defer file.Close()

        var p Person
        decoder := gob.NewDecoder(file)
        decoder.Decode(&p)
        ---

03.注意事项
    a.导出字段
        只有导出的字段(首字母大写)才能被序列化
    b.类型注册
        对于接口类型需要先注册具体类型
        ---
        gob.Register(ConcreteType{})
        ---

2.5 Protocol Buffers

01.Protocol Buffers概述
    a.定义
        Protocol Buffers是Google开发的数据序列化格式
        跨语言、高效、向后兼容
    b.特点
        二进制格式,体积小
        强类型,编译时检查
        支持多种语言
        向后兼容性好

02.使用步骤
    a.安装protoc编译器
        ---
        // 下载并安装protoc
        // https://github.com/protocolbuffers/protobuf/releases
        ---
    b.安装Go插件
        ---
        go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
        ---
    c.定义.proto文件
        ---
        syntax = "proto3";

        package main;

        option go_package = "./;main";

        message Person {
            string name = 1;
            int32 age = 2;
            string email = 3;
        }
        ---
    d.生成Go代码
        ---
        protoc --go_out=. person.proto
        ---

03.使用示例
    a.序列化
        ---
        package main

        import (
            "fmt"
            "google.golang.org/protobuf/proto"
        )

        func main() {
            p := &Person{
                Name:  "张三",
                Age:   25,
                Email: "[email protected]",
            }

            // 序列化
            data, err := proto.Marshal(p)
            if err != nil {
                fmt.Println("序列化错误:", err)
                return
            }
            fmt.Println("序列化后大小:", len(data))
        }
        ---
    b.反序列化
        ---
        var p2 Person
        err := proto.Unmarshal(data, &p2)
        if err != nil {
            fmt.Println("反序列化错误:", err)
            return
        }
        fmt.Printf("%+v\n", &p2)
        ---

04.优势对比
    a.与JSON对比
        体积更小,约为JSON的1/3
        解析速度更快
        强类型,更安全
    b.适用场景
        微服务���通信
        大数据传输
        需要向后兼容的系统

3 网络IO

3.1 TCP编程

01.TCP服务端
    a.创建监听器
        ---
        listener, err := net.Listen("tcp", ":8080")
        if err != nil {
            log.Fatal(err)
        }
        defer listener.Close()
        ---
    b.接受连接
        ---
        conn, err := listener.Accept()
        if err != nil {
            log.Println(err)
            continue
        }
        go handleConnection(conn)
        ---
    c.完整示例
        ---
        package main

        import (
            "bufio"
            "fmt"
            "log"
            "net"
        )

        func handleConnection(conn net.Conn) {
            defer conn.Close()

            reader := bufio.NewReader(conn)
            for {
                message, err := reader.ReadString('\n')
                if err != nil {
                    return
                }
                fmt.Print("收到消息: ", message)

                // 回复客户端
                conn.Write([]byte("收到: " + message))
            }
        }

        func main() {
            listener, err := net.Listen("tcp", ":8080")
            if err != nil {
                log.Fatal(err)
            }
            defer listener.Close()

            fmt.Println("服务器启动在 :8080")

            for {
                conn, err := listener.Accept()
                if err != nil {
                    log.Println(err)
                    continue
                }
                go handleConnection(conn)
            }
        }
        ---

02.TCP客户端
    a.连接服务器
        ---
        conn, err := net.Dial("tcp", "localhost:8080")
        if err != nil {
            log.Fatal(err)
        }
        defer conn.Close()
        ---
    b.发送和接收数据
        ---
        // 发送数据
        conn.Write([]byte("Hello, Server!\n"))

        // 接收数据
        reader := bufio.NewReader(conn)
        response, _ := reader.ReadString('\n')
        fmt.Print("服务器回复: ", response)
        ---
    c.完整示例
        ---
        package main

        import (
            "bufio"
            "fmt"
            "log"
            "net"
        )

        func main() {
            conn, err := net.Dial("tcp", "localhost:8080")
            if err != nil {
                log.Fatal(err)
            }
            defer conn.Close()

            // 发送消息
            message := "Hello, Server!\n"
            conn.Write([]byte(message))

            // 接收回复
            reader := bufio.NewReader(conn)
            response, err := reader.ReadString('\n')
            if err != nil {
                log.Fatal(err)
            }
            fmt.Print("服务器回复: ", response)
        }
        ---

03.TCP连接管理
    a.设置超时
        ---
        conn.SetDeadline(time.Now().Add(5 * time.Second))
        conn.SetReadDeadline(time.Now().Add(5 * time.Second))
        conn.SetWriteDeadline(time.Now().Add(5 * time.Second))
        ---
    b.获取连接信息
        ---
        localAddr := conn.LocalAddr()
        remoteAddr := conn.RemoteAddr()
        fmt.Println("本地地址:", localAddr)
        fmt.Println("远程地址:", remoteAddr)
        ---

3.2 UDP编程

01.UDP服务端
    a.创建UDP监听
        ---
        addr, err := net.ResolveUDPAddr("udp", ":8080")
        conn, err := net.ListenUDP("udp", addr)
        if err != nil {
            log.Fatal(err)
        }
        defer conn.Close()
        ---
    b.完整示例
        ---
        package main

        import (
            "fmt"
            "log"
            "net"
        )

        func main() {
            addr, err := net.ResolveUDPAddr("udp", ":8080")
            if err != nil {
                log.Fatal(err)
            }

            conn, err := net.ListenUDP("udp", addr)
            if err != nil {
                log.Fatal(err)
            }
            defer conn.Close()

            fmt.Println("UDP服务器启动在 :8080")

            buffer := make([]byte, 1024)
            for {
                n, clientAddr, err := conn.ReadFromUDP(buffer)
                if err != nil {
                    log.Println(err)
                    continue
                }

                fmt.Printf("收到来自 %s 的消息: %s\n", clientAddr, buffer[:n])

                // 回复客户端
                conn.WriteToUDP([]byte("收到: "+string(buffer[:n])), clientAddr)
            }
        }
        ---

02.UDP客户端
    a.发送数据
        ---
        addr, err := net.ResolveUDPAddr("udp", "localhost:8080")
        conn, err := net.DialUDP("udp", nil, addr)
        if err != nil {
            log.Fatal(err)
        }
        defer conn.Close()

        conn.Write([]byte("Hello, UDP Server!"))
        ---
    b.完整示例
        ---
        package main

        import (
            "fmt"
            "log"
            "net"
        )

        func main() {
            addr, err := net.ResolveUDPAddr("udp", "localhost:8080")
            if err != nil {
                log.Fatal(err)
            }

            conn, err := net.DialUDP("udp", nil, addr)
            if err != nil {
                log.Fatal(err)
            }
            defer conn.Close()

            // 发送消息
            message := "Hello, UDP Server!"
            conn.Write([]byte(message))

            // 接收回复
            buffer := make([]byte, 1024)
            n, err := conn.Read(buffer)
            if err != nil {
                log.Fatal(err)
            }
            fmt.Printf("服务器回复: %s\n", buffer[:n])
        }
        ---

03.UDP特点
    a.无连接
        UDP不需要建立连接,直接发送数据
    b.不可靠
        不保证数据到达,不保证顺序
    c.高效
        开销小,适合实时应用
    d.适用场景
        视频流传输
        在线游戏
        DNS查询
        实时通信

3.3 HTTP编程

01.HTTP服务端
    a.简单HTTP服务器
        ---
        package main

        import (
            "fmt"
            "net/http"
        )

        func handler(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
        }

        func main() {
            http.HandleFunc("/", handler)
            http.ListenAndServe(":8080", nil)
        }
        ---
    b.处理不同HTTP方法
        ---
        func handler(w http.ResponseWriter, r *http.Request) {
            switch r.Method {
            case "GET":
                fmt.Fprintf(w, "GET请求")
            case "POST":
                fmt.Fprintf(w, "POST请求")
            default:
                w.WriteHeader(http.StatusMethodNotAllowed)
            }
        }
        ---
    c.读取请求体
        ---
        func handler(w http.ResponseWriter, r *http.Request) {
            body, err := io.ReadAll(r.Body)
            if err != nil {
                http.Error(w, "读取错误", http.StatusBadRequest)
                return
            }
            defer r.Body.Close()

            fmt.Fprintf(w, "收到数据: %s", body)
        }
        ---

02.HTTP客户端
    a.GET请求
        ---
        package main

        import (
            "fmt"
            "io"
            "net/http"
        )

        func main() {
            resp, err := http.Get("http://example.com")
            if err != nil {
                fmt.Println("请求错误:", err)
                return
            }
            defer resp.Body.Close()

            body, _ := io.ReadAll(resp.Body)
            fmt.Println(string(body))
        }
        ---
    b.POST请求
        ---
        package main

        import (
            "bytes"
            "fmt"
            "io"
            "net/http"
        )

        func main() {
            data := []byte(`{"name":"张��","age":25}`)
            resp, err := http.Post(
                "http://example.com/api",
                "application/json",
                bytes.NewBuffer(data),
            )
            if err != nil {
                fmt.Println("请求错误:", err)
                return
            }
            defer resp.Body.Close()

            body, _ := io.ReadAll(resp.Body)
            fmt.Println(string(body))
        }
        ---
    c.自定义请求
        ---
        req, err := http.NewRequest("PUT", "http://example.com/api", nil)
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer token")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
            fmt.Println("请求错误:", err)
            return
        }
        defer resp.Body.Close()
        ---

03.HTTP高级特性
    a.设置超时
        ---
        client := &http.Client{
            Timeout: 10 * time.Second,
        }
        resp, err := client.Get("http://example.com")
        ---
    b.处理Cookie
        ---
        cookie := &http.Cookie{
            Name:  "session",
            Value: "abc123",
        }
        http.SetCookie(w, cookie)

        // 读取Cookie
        cookie, err := r.Cookie("session")
        ---
    c.文件上传
        ---
        func uploadHandler(w http.ResponseWriter, r *http.Request) {
            file, header, err := r.FormFile("file")
            if err != nil {
                http.Error(w, err.Error(), http.StatusBadRequest)
                return
            }
            defer file.Close()

            fmt.Fprintf(w, "上传文件: %s", header.Filename)
        }
        ---

3.4 WebSocket

01.WebSocket概述
    a.定义
        WebSocket是一种全双工通信协议
        建立在TCP之上,支持持久连接
    b.特点
        双向通信:服务器可主动推送消息
        低延迟:保持连接,无需重复握手
        实时性:适合实时应用
    c.使用场景
        聊天应用
        实时通知
        在线游戏
        协作编辑

02.使用gorilla/websocket库
    a.安装
        ---
        go get github.com/gorilla/websocket
        ---
    b.服务端示例
        ---
        package main

        import (
            "fmt"
            "log"
            "net/http"

            "github.com/gorilla/websocket"
        )

        var upgrader = websocket.Upgrader{
            CheckOrigin: func(r *http.Request) bool {
                return true
            },
        }

        func handleWebSocket(w http.ResponseWriter, r *http.Request) {
            conn, err := upgrader.Upgrade(w, r, nil)
            if err != nil {
                log.Println(err)
                return
            }
            defer conn.Close()

            for {
                messageType, message, err := conn.ReadMessage()
                if err != nil {
                    log.Println(err)
                    break
                }

                fmt.Printf("收到消息: %s\n", message)

                // 回复消息
                err = conn.WriteMessage(messageType, message)
                if err != nil {
                    log.Println(err)
                    break
                }
            }
        }

        func main() {
            http.HandleFunc("/ws", handleWebSocket)
            log.Fatal(http.ListenAndServe(":8080", nil))
        }
        ---
    c.客户端示例
        ---
        package main

        import (
            "fmt"
            "log"

            "github.com/gorilla/websocket"
        )

        func main() {
            url := "ws://localhost:8080/ws"
            conn, _, err := websocket.DefaultDialer.Dial(url, nil)
            if err != nil {
                log.Fatal(err)
            }
            defer conn.Close()

            // 发送消息
            err = conn.WriteMessage(websocket.TextMessage, []byte("Hello, WebSocket!"))
            if err != nil {
                log.Fatal(err)
            }

            // 接收消息
            _, message, err := conn.ReadMessage()
            if err != nil {
                log.Fatal(err)
            }
            fmt.Printf("收到回复: %s\n", message)
        }
        ---

03.WebSocket消息类型
    a.文本消息
        ---
        conn.WriteMessage(websocket.TextMessage, []byte("文本消息"))
        ---
    b.二进制消息
        ---
        conn.WriteMessage(websocket.BinaryMessage, data)
        ---
    c.控制消息
        ---
        // Ping消息
        conn.WriteMessage(websocket.PingMessage, nil)

        // Pong消息
        conn.WriteMessage(websocket.PongMessage, nil)

        // Close消息
        conn.WriteMessage(websocket.CloseMessage, nil)
        ---

04.WebSocket最佳实践
    a.心跳检测
        ---
        ticker := time.NewTicker(30 * time.Second)
        defer ticker.Stop()

        for {
            select {
            case <-ticker.C:
                if err := conn.WriteMessage(websocket.PingMessage, nil); err != nil {
                    return
                }
            }
        }
        ---
    b.并发读写
        ---
        // 读goroutine
        go func() {
            for {
                _, message, err := conn.ReadMessage()
                if err != nil {
                    return
                }
                handleMessage(message)
            }
        }()

        // 写goroutine
        go func() {
            for msg := range sendChan {
                conn.WriteMessage(websocket.TextMessage, msg)
            }
        }()
        ---

4 高级IO

4.1 io.Pipe管道

01.管道概念
    a.定义
        io.Pipe创建一个同步的内存管道
        连接一个Reader和一个Writer
    b.特点
        同步操作:写入会阻塞直到读取
        无缓冲:数据直接传递
        线程安全:可在不同goroutine中使用

02.基本使用
    a.创建管道
        ---
        r, w := io.Pipe()
        ---
    b.简单示例
        ---
        package main

        import (
            "fmt"
            "io"
        )

        func main() {
            r, w := io.Pipe()

            // 写入goroutine
            go func() {
                defer w.Close()
                w.Write([]byte("Hello, Pipe!"))
            }()

            // 读取
            data, _ := io.ReadAll(r)
            fmt.Println(string(data))
        }
        ---

03.应用场景
    a.数据流转换
        ---
        package main

        import (
            "compress/gzip"
            "io"
            "os"
        )

        func main() {
            r, w := io.Pipe()

            // 写入原始数据
            go func() {
                defer w.Close()
                w.Write([]byte("需要压缩的数据"))
            }()

            // 压缩并写入文件
            file, _ := os.Create("output.gz")
            defer file.Close()

            gzipWriter := gzip.NewWriter(file)
            defer gzipWriter.Close()

            io.Copy(gzipWriter, r)
        }
        ---
    b.并发处理
        ---
        r, w := io.Pipe()

        // 生产者
        go func() {
            defer w.Close()
            for i := 0; i < 10; i++ {
                fmt.Fprintf(w, "数据 %d\n", i)
            }
        }()

        // 消费者
        scanner := bufio.NewScanner(r)
        for scanner.Scan() {
            fmt.Println("处理:", scanner.Text())
        }
        ---

4.2 io.Copy数据复制

01.io.Copy基础
    a.函数签名
        ---
        func Copy(dst Writer, src Reader) (written int64, err error)
        ---
    b.功能说明
        从src读取数据并写入dst
        返回复制的字节数和错误
        自动处理缓冲区

02.基本使用
    a.文件复制
        ---
        package main

        import (
            "io"
            "log"
            "os"
        )

        func main() {
            src, err := os.Open("source.txt")
            if err != nil {
                log.Fatal(err)
            }
            defer src.Close()

            dst, err := os.Create("dest.txt")
            if err != nil {
                log.Fatal(err)
            }
            defer dst.Close()

            n, err := io.Copy(dst, src)
            if err != nil {
                log.Fatal(err)
            }
            log.Printf("���制了 %d 字节", n)
        }
        ---
    b.网络数据转发
        ---
        func handleConnection(conn net.Conn) {
            defer conn.Close()

            // 将连接数据复制到标准输出
            io.Copy(os.Stdout, conn)
        }
        ---

03.相关函数
    a.io.CopyN
        功能:复制指定字节数
        ---
        n, err := io.CopyN(dst, src, 1024) // 复制1024字节
        ---
    b.io.CopyBuffer
        功能:使用指定缓冲区复制
        ---
        buf := make([]byte, 32*1024) // 32KB缓冲区
        n, err := io.CopyBuffer(dst, src, buf)
        ---

04.实用示例
    a.下载文件
        ---
        package main

        import (
            "io"
            "log"
            "net/http"
            "os"
        )

        func downloadFile(url, filepath string) error {
            resp, err := http.Get(url)
            if err != nil {
                return err
            }
            defer resp.Body.Close()

            file, err := os.Create(filepath)
            if err != nil {
                return err
            }
            defer file.Close()

            _, err = io.Copy(file, resp.Body)
            return err
        }

        func main() {
            err := downloadFile("http://example.com/file.zip", "file.zip")
            if err != nil {
                log.Fatal(err)
            }
        }
        ---
    b.数据压缩
        ---
        package main

        import (
            "compress/gzip"
            "io"
            "os"
        )

        func compressFile(src, dst string) error {
            srcFile, _ := os.Open(src)
            defer srcFile.Close()

            dstFile, _ := os.Create(dst)
            defer dstFile.Close()

            gzipWriter := gzip.NewWriter(dstFile)
            defer gzipWriter.Close()

            _, err := io.Copy(gzipWriter, srcFile)
            return err
        }
        ---

4.3 io.MultiReader多路读取

01.MultiReader概念
    a.定义
        将多个Reader合并为一个Reader
        按顺序读取每个Reader的内容
    b.函数签名
        ---
        func MultiReader(readers ...Reader) Reader
        ---

02.基本使用
    a.合并多个字符串
        ---
        package main

        import (
            "fmt"
            "io"
            "strings"
        )

        func main() {
            r1 := strings.NewReader("Hello, ")
            r2 := strings.NewReader("Go ")
            r3 := strings.NewReader("World!")

            r := io.MultiReader(r1, r2, r3)

            data, _ := io.ReadAll(r)
            fmt.Println(string(data)) // Hello, Go World!
        }
        ---
    b.合并文件内容
        ---
        package main

        import (
            "io"
            "log"
            "os"
        )

        func main() {
            file1, _ := os.Open("part1.txt")
            defer file1.Close()

            file2, _ := os.Open("part2.txt")
            defer file2.Close()

            file3, _ := os.Open("part3.txt")
            defer file3.Close()

            // 合并三个文件
            r := io.MultiReader(file1, file2, file3)

            // 写入到新文件
            output, _ := os.Create("merged.txt")
            defer output.Close()

            _, err := io.Copy(output, r)
            if err != nil {
                log.Fatal(err)
            }
        }
        ---

03.应用场景
    a.添加文件头尾
        ---
        header := strings.NewReader("=== 文件开始 ===\n")
        content, _ := os.Open("content.txt")
        footer := strings.NewReader("\n=== 文件结束 ===")

        r := io.MultiReader(header, content, footer)
        io.Copy(os.Stdout, r)
        ---
    b.组合配置文件
        ---
        defaultConfig := strings.NewReader("default settings\n")
        userConfig, _ := os.Open("user.conf")

        r := io.MultiReader(defaultConfig, userConfig)
        // 处理合并后的配置
        ---

4.4 io.TeeReader分流读取

01.TeeReader概念
    a.定义
        从Reader读取数据的同时写入Writer
        类似Unix的tee命令
    b.函数签名
        ---
        func TeeReader(r Reader, w Writer) Reader
        ---

02.基本使用
    a.读取并保存
        ---
        package main

        import (
            "fmt"
            "io"
            "os"
            "strings"
        )

        func main() {
            r := strings.NewReader("Hello, TeeReader!")

            // 创建文件用于保存
            file, _ := os.Create("output.txt")
            defer file.Close()

            // 创建TeeReader
            tee := io.TeeReader(r, file)

            // 读取数据(同时写入文件)
            data, _ := io.ReadAll(tee)
            fmt.Println(string(data))
        }
        ---
    b.网络数据监控
        ---
        package main

        import (
            "io"
            "log"
            "net/http"
            "os"
        )

        func main() {
            resp, err := http.Get("http://example.com")
            if err != nil {
                log.Fatal(err)
            }
            defer resp.Body.Close()

            // 创建日志文件
            logFile, _ := os.Create("request.log")
            defer logFile.Close()

            // 读取响应的同时记录到日志
            tee := io.TeeReader(resp.Body, logFile)

            // 处理响应数据
            data, _ := io.ReadAll(tee)
            log.Printf("收到 %d 字节", len(data))
        }
        ---

03.应用场景
    a.数据备份
        ---
        // 读取文件的同时备份
        src, _ := os.Open("source.txt")
        backup, _ := os.Create("backup.txt")

        tee := io.TeeReader(src, backup)
        // 处理数据的同时自动备份
        processData(tee)
        ---
    b.数据校验
        ---
        package main

        import (
            "crypto/md5"
            "io"
            "os"
        )

        func main() {
            file, _ := os.Open("data.bin")
            defer file.Close()

            // 计算MD5的同时读取数据
            hash := md5.New()
            tee := io.TeeReader(file, hash)

            // 处理数据
            data, _ := io.ReadAll(tee)

            // 获取MD5值
            checksum := hash.Sum(nil)
            // 使用data和checksum
        }
        ---

04.组合使用
    a.多重分流
        ---
        package main

        import (
            "io"
            "os"
        )

        func main() {
            src, _ := os.Open("source.txt")

            log1, _ := os.Create("log1.txt")
            log2, _ := os.Create("log2.txt")

            // 创建MultiWriter
            mw := io.MultiWriter(log1, log2)

            // 读取的同时写入多个文件
            tee := io.TeeReader(src, mw)

            io.Copy(os.Stdout, tee)
        }
        ---

4.5 context上下文控制

01.Context概念
    a.定义
        Context用于在goroutine之间传递截止时间、取消信号和请求范围的值
    b.主要用途
        超时控制
        取消操作
        传递请求范围的数据

02.Context类型
    a.context.Background
        ---
        ctx := context.Background()
        ---
        根Context,通常用于main函数、初始化和测试
    b.context.TODO
        ---
        ctx := context.TODO()
        ---
        当不确定使用哪个Context时使用
    c.context.WithCancel
        ---
        ctx, cancel := context.WithCancel(context.Background())
        defer cancel()
        ---
        可手动取消的Context
    d.context.WithTimeout
        ---
        ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()
        ---
        超时自动取消
    e.context.WithDeadline
        ---
        deadline := time.Now().Add(5 * time.Second)
        ctx, cancel := context.WithDeadline(context.Background(), deadline)
        defer cancel()
        ---
        指定截止时间

03.IO操作中使用Context
    a.HTTP请求超时
        ---
        package main

        import (
            "context"
            "fmt"
            "io"
            "net/http"
            "time"
        )

        func main() {
            ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
            defer cancel()

            req, _ := http.NewRequestWithContext(ctx, "GET", "http://example.com", nil)

            resp, err := http.DefaultClient.Do(req)
            if err != nil {
                fmt.Println("请求错误:", err)
                return
            }
            defer resp.Body.Close()

            body, _ := io.ReadAll(resp.Body)
            fmt.Println(string(body))
        }
        ---
    b.文件操作超时
        ---
        package main

        import (
            "context"
            "fmt"
            "time"
        )

        func readFileWithTimeout(ctx context.Context, filename string) error {
            done := make(chan error, 1)

            go func() {
                // 执行文件读取操作
                // ...
                done <- nil
            }()

            select {
            case err := <-done:
                return err
            case <-ctx.Done():
                return ctx.Err()
            }
        }

        func main() {
            ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
            defer cancel()

            err := readFileWithTimeout(ctx, "large_file.txt")
            if err != nil {
                fmt.Println("操作失败:", err)
            }
        }
        ---

04.Context最佳实践
    a.传递Context
        ---
        // 将Context作为第一个参数传递
        func DoSomething(ctx context.Context, arg string) error {
            // 检查Context是否已取消
            select {
            case <-ctx.Done():
                return ctx.Err()
            default:
            }

            // 执行操作
            return nil
        }
        ---
    b.监听取消信号
        ---
        func worker(ctx context.Context) {
            for {
                select {
                case <-ctx.Done():
                    fmt.Println("收到取消信号")
                    return
                default:
                    // 执行工作
                    time.Sleep(100 * time.Millisecond)
                }
            }
        }
        ---
    c.传递值
        ---
        type key string

        const userKey key = "user"

        ctx := context.WithValue(context.Background(), userKey, "张三")

        // 获取值
        if user, ok := ctx.Value(userKey).(string); ok {
            fmt.Println("用户:", user)
        }
        ---