Java转Go全过程04-网络编程部分

Java教程 2025-09-03

Java开发已经是红海一片,面临着35岁危机的压力,需要适时的调整策略,以应对可能会出现的不确定性。毕竟,命运掌握在自己手里,比掌握在公司手里 安全感会强很多。

尝试的其中一条路即为:Java转Go,海外开发web3相关,也有其他的尝试,会开辟相应的专栏收录。

针对每一个部分,都会在最后准备练习题,可以多做几遍,用于巩固知识,多动手!

Go语言基础快速突破[网络编程](1-2周)

1. Socket编程

1.1 Dial()函数

Go语言提供了简洁的网络连接方式,通过net.Dial()函数可以轻松建立网络连接:

package main

import (
    "fmt"
    "net"
)

func main() {
    conn, err := net.Dial("tcp", "www.google.com:80")
    if err != nil {
        fmt.Println("连接失败:", err)
        return
    }
    defer conn.Close()
    fmt.Println("连接成功")
}

关键点:

  • 支持多种网络协议:tcp、udp、unix等
  • 自动处理DNS解析
  • 返回连接对象和错误信息

1.2 ICMP示例程序

ICMP(Internet Control Message Protocol)用于网络诊断,类似ping命令:

package main

import (
    "fmt"
    "net"
    "os"
    "time"
)

func main() {
    conn, err := net.Dial("ip4:icmp", "www.baidu.com")
    if err != nil {
        fmt.Println("ICMP连接失败:", err)
        os.Exit(1)
    }
    defer conn.Close()
    
    // 发送ICMP回显请求
    data := []byte("Hello ICMP")
    _, err = conn.Write(data)
    if err != nil {
        fmt.Println("发送失败:", err)
        return
    }
    
    // 设置读取超时
    conn.SetReadDeadline(time.Now().Add(3 * time.Second))
    
    buffer := make([]byte, 1024)
    n, err := conn.Read(buffer)
    if err != nil {
        fmt.Println("读取失败:", err)
        return
    }
    
    fmt.Printf("收到回复: %sn", string(buffer[:n]))
}

1.3 TCP示例程序

TCP是最常用的可靠传输协议:

TCP客户端:

package main

import (
    "fmt"
    "net"
)

func main() {
    // 连接到TCP服务器
    conn, err := net.Dial("tcp", "localhost:8080")
    if err != nil {
        fmt.Println("连接失败:", err)
        return
    }
    defer conn.Close()
    
    // 发送数据
    message := "Hello TCP Server"
    _, err = conn.Write([]byte(message))
    if err != nil {
        fmt.Println("发送失败:", err)
        return
    }
    
    // 读取响应
    buffer := make([]byte, 1024)
    n, err := conn.Read(buffer)
    if err != nil {
        fmt.Println("读取失败:", err)
        return
    }
    
    fmt.Printf("服务器响应: %sn", string(buffer[:n]))
}

TCP服务端:

package main

import (
    "fmt"
    "net"
)

func main() {
    // 监听TCP端口
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        fmt.Println("监听失败:", err)
        return
    }
    defer listener.Close()
    
    fmt.Println("TCP服务器启动,监听端口8080...")
    
    for {
        // 接受客户端连接
        conn, err := listener.Accept()
        if err != nil {
            fmt.Println("接受连接失败:", err)
            continue
        }
        
        // 处理客户端请求
        go handleClient(conn)
    }
}

func handleClient(conn net.Conn) {
    defer conn.Close()
    
    buffer := make([]byte, 1024)
    n, err := conn.Read(buffer)
    if err != nil {
        fmt.Println("读取失败:", err)
        return
    }
    
    fmt.Printf("收到客户端消息: %sn", string(buffer[:n]))
    
    // 回复客户端
    response := "消息已收到"
    _, err = conn.Write([]byte(response))
    if err != nil {
        fmt.Println("回复失败:", err)
    }
}

1.4 更丰富的网络通信

包括UDP通信、Unix域套接字等:

// UDP示例
conn, err := net.Dial("udp", "localhost:8081")
// Unix域套接字示例
conn, err := net.Dial("unix", "/tmp/socket")

2. HTTP编程

2.1 HTTP客户端

Go语言的net/http包提供了强大的HTTP客户端功能:

package main

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

func main() {
    // GET请求
    resp, err := http.Get("https://api.*gi*thu*b.com/users/golang")
    if err != nil {
        fmt.Println("请求失败:", err)
        return
    }
    defer resp.Body.Close()
    
    body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("读取响应失败:", err)
        return
    }
    
    fmt.Printf("状态码: %dn", resp.StatusCode)
    fmt.Printf("响应内容: %sn", string(body))
}

自定义HTTP客户端:

client := &http.Client{
    Timeout: time.Second * 30,
}

req, err := http.NewRequest("POST", "https://api.*ex**ample.com", strings.NewReader("data"))
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)

2.2 HTTP服务端

创建HTTP服务器非常简单:

package main

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

func main() {
    // 注册路由处理器
    http.HandleFunc("/", homeHandler)
    http.HandleFunc("/api/users", usersHandler)
    
    fmt.Println("HTTP服务器启动,监听端口8080...")
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        fmt.Println("服务器启动失败:", err)
    }
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "欢迎访问Go HTTP服务器!")
}

func usersHandler(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case "GET":
        fmt.Fprintf(w, "获取用户列表")
    case "POST":
        fmt.Fprintf(w, "创建新用户")
    default:
        http.Error(w, "方法不支持", http.StatusMethodNotAllowed)
    }
}

3. RPC编程

3.1 Go语言中的RPC支持与处理

Go语言内置了RPC(远程过程调用)支持:

RPC服务端:

package main

import (
    "net"
    "net/rpc"
)

type Calculator struct{}

type Args struct {
    A, B int
}

func (c *Calculator) Add(args *Args, reply *int) error {
    *reply = args.A + args.B
    return nil
}

func (c *Calculator) Multiply(args *Args, reply *int) error {
    *reply = args.A * args.B
    return nil
}

func main() {
    calc := new(Calculator)
    rpc.Register(calc)
    
    listener, err := net.Listen("tcp", ":8081")
    if err != nil {
        panic(err)
    }
    defer listener.Close()
    
    for {
        conn, err := listener.Accept()
        if err != nil {
            continue
        }
        go rpc.ServeConn(conn)
    }
}

RPC客户端:

package main

import (
    "fmt"
    "net/rpc"
)

type Args struct {
    A, B int
}

func main() {
    client, err := rpc.Dial("tcp", "localhost:8081")
    if err != nil {
        panic(err)
    }
    defer client.Close()
    
    args := &Args{7, 8}
    var reply int
    
    err = client.Call("Calculator.Add", args, &reply)
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("7 + 8 = %dn", reply)
}

3.2 Gob简介

Gob是Go语言特有的序列化格式,用于RPC通信:

package main

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

type Person struct {
    Name string
    Age  int
}

func main() {
    // 编码
    var buffer bytes.Buffer
    encoder := gob.NewEncoder(&buffer)
    
    person := Person{Name: "张三", Age: 30}
    err := encoder.Encode(person)
    if err != nil {
        panic(err)
    }
    
    // 解码
    decoder := gob.NewDecoder(&buffer)
    var decodedPerson Person
    err = decoder.Decode(&decodedPerson)
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("解码结果: %+vn", decodedPerson)
}

3.3 设计优雅的RPC接口

良好的RPC接口设计原则:

// 定义清晰的服务接口
type UserService interface {
    GetUser(id int) (*User, error)
    CreateUser(user *User) error
    UpdateUser(user *User) error
    DeleteUser(id int) error
}

// 实现服务
type UserServiceImpl struct {
    users map[int]*User
}

func (s *UserServiceImpl) GetUser(id int, user *User) error {
    if u, exists := s.users[id]; exists {
        *user = *u
        return nil
    }
    return fmt.Errorf("用户不存在: %d", id)
}

4. JSON处理

4.1 编码为JSON格式

将Go数据结构转换为JSON:

package main

import (
    "encoding/json"
    "fmt"
)

type User struct {
    ID       int    `json:"id"`
    Name     string `json:"name"`
    Email    string `json:"email"`
    IsActive bool   `json:"is_active"`
}

func main() {
    user := User{
        ID:       1,
        Name:     "张三",
        Email:    "zhangsan@example.com",
        IsActive: true,
    }
    
    // 编码为JSON
    jsonData, err := json.Marshal(user)
    if err != nil {
        fmt.Println("JSON编码失败:", err)
        return
    }
    
    fmt.Printf("JSON数据: %sn", string(jsonData))
    
    // 美化输出
    jsonPretty, err := json.MarshalIndent(user, "", "  ")
    if err != nil {
        fmt.Println("美化JSON失败:", err)
        return
    }
    
    fmt.Printf("美化的JSON:n%sn", string(jsonPretty))
}

4.2 解码JSON数据

将JSON数据转换为Go数据结构:

package main

import (
    "encoding/json"
    "fmt"
)

type User struct {
    ID       int    `json:"id"`
    Name     string `json:"name"`
    Email    string `json:"email"`
    IsActive bool   `json:"is_active"`
}

func main() {
    jsonStr := `{"id":1,"name":"李四","email":"lisi@example.com","is_active":true}`
    
    var user User
    err := json.Unmarshal([]byte(jsonStr), &user)
    if err != nil {
        fmt.Println("JSON解码失败:", err)
        return
    }
    
    fmt.Printf("解码结果: %+vn", user)
}

4.3 解码未知结构的JSON数据

处理动态JSON结构:

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    jsonStr := `{
        "name": "王五",
        "age": 25,
        "skills": ["Go", "Python", "JavaScript"],
        "address": {
            "city": "北京",
            "district": "朝阳区"
        }
    }`
    
    var data map[string]interface{}
    err := json.Unmarshal([]byte(jsonStr), &data)
    if err != nil {
        fmt.Println("解码失败:", err)
        return
    }
    
    fmt.Printf("姓名: %sn", data["name"])
    fmt.Printf("年龄: %.0fn", data["age"])
    
    // 处理数组
    if skills, ok := data["skills"].([]interface{}); ok {
        fmt.Print("技能: ")
        for _, skill := range skills {
            fmt.Printf("%s ", skill)
        }
        fmt.Println()
    }
    
    // 处理嵌套对象
    if address, ok := data["address"].(map[string]interface{}); ok {
        fmt.Printf("地址: %s %sn", address["city"], address["district"])
    }
}

4.4 JSON的流式读写

处理大型JSON数据时使用流式处理:

package main

import (
    "encoding/json"
    "fmt"
    "strings"
)

func main() {
    jsonStream := `
        {"name":"用户1","age":20}
        {"name":"用户2","age":25}
        {"name":"用户3","age":30}
    `
    
    decoder := json.NewDecoder(strings.NewReader(jsonStream))
    
    for decoder.More() {
        var user map[string]interface{}
        err := decoder.Decode(&user)
        if err != nil {
            fmt.Println("解码失败:", err)
            break
        }
        fmt.Printf("用户: %s, 年龄: %.0fn", user["name"], user["age"])
    }
}

5. 网站开发

5.1 最简单的网站程序

创建一个基础的Web服务器:

package main

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

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "

欢迎来到Go Web世界!

"
) fmt.Fprintf(w, "

当前时间: %s

"
, time.Now().Format("2006-01-02 15:04:05")) }) fmt.Println("Web服务器启动,访问 http://*loc*alhost*:8080") http.ListenAndServe(":8080", nil) }

5.2 net/http包简介

Go的net/http包功能强大,包含:

核心组件:

  • http.Handler接口:处理HTTP请求的核心接口
  • http.ServeMux:HTTP请求路由器
  • http.Server:HTTP服务器配置

中间件示例:

package main

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

func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Printf("请求: %s %sn", r.Method, r.URL.Path)
        next.ServeHTTP(w, r)
    })
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/api", apiHandler)
    
    // 应用中间件
    handler := loggingMiddleware(mux)
    
    server := &http.Server{
        Addr:         ":8080",
        Handler:      handler,
        ReadTimeout:  10 * time.Second,
        WriteTimeout: 10 * time.Second,
    }
    
    server.ListenAndServe()
}

func apiHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "API响应")
}

5.3 开发一个简单的相册网站

构建一个完整的相册应用:

package main

import (
    "html/template"
    "net/http"
    "fmt"
)

type Photo struct {
    ID       int
    Title    string
    Filename string
    Caption  string
}

type Album struct {
    Title  string
    Photos []Photo
}

func main() {
    // 静态文件服务
    http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static/"))))
    
    // 路由
    http.HandleFunc("/", albumHandler)
    http.HandleFunc("/photo/", photoHandler)
    http.HandleFunc("/upload", uploadHandler)
    
    fmt.Println("相册网站启动,访问 http://*loc*alhost*:8080")
    http.ListenAndServe(":8080", nil)
}

func albumHandler(w http.ResponseWriter, r *http.Request) {
    album := Album{
        Title: "我的相册",
        Photos: []Photo{
            {1, "风景照", "landscape.jpg", "美丽的风景"},
            {2, "人物照", "portrait.jpg", "朋友合影"},
        },
    }
    
    tmpl := `
    
    
    
        {{.Title}}
        
    
    
        

{{.Title}}

{{range .Photos}}
{{.Title}}

{{.Caption}}

{{end}} 上传新照片 `
t, _ := template.New("album").Parse(tmpl) t.Execute(w, album) } func photoHandler(w http.ResponseWriter, r *http.Request) { // 处理单张照片显示 fmt.Fprintf(w, "照片详情页面") } func uploadHandler(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { // 处理文件上传 file, header, err := r.FormFile("photo") if err != nil { http.Error(w, "上传失败", http.StatusBadRequest) return } defer file.Close() fmt.Printf("上传文件: %sn", header.Filename) fmt.Fprintf(w, "文件上传成功: %s", header.Filename) } else { // 显示上传表单 uploadForm := ` 上传照片

上传新照片



返回相册 `
fmt.Fprintf(w, uploadForm) } }

学习建议

  1. 循序渐进:从Socket基础开始,逐步掌握HTTP和RPC
  2. 动手实践:每个示例都要亲自运行和修改
  3. 理解原理:不仅要会用,还要理解底层网络原理
  4. 项目实战:尝试构建完整的网络应用项目
  5. 性能优化:学习连接池、超时控制等高级特性

练习题

package main

import (
	"bufio"
	"bytes"
	"encoding/gob"
	"encoding/json"
	"fmt"
	"html/template"
	"io"
	"log"
	"net"
	"net/http"
	"net/rpc"
	//"os"
	"strconv"
	"strings"
	"time"
)

/*
===========================================
Go语言网络编程练习题集
===========================================

本文件包含了Go语言网络编程的完整练习题和标准答案,涵盖:
1. Socket编程
2. HTTP编程
3. RPC编程
4. JSON处理
5. 网站开发

每个练习都有详细的题目描述、实现代码和运行说明。
*/

// ===========================================
// 第1章:Socket编程练习
// ===========================================

// 练习1.1:使用Dial()函数连接远程服务器
func exercise1_1() {
	fmt.Println("n=== 练习1.1:Dial()函数连接测试 ===")

	// 题目:使用net.Dial()连接到百度服务器,检查连接状态
	conn, err := net.Dial("tcp", "www.baidu.com:80")
	if err != nil {
		fmt.Printf("连接失败: %vn", err)
		return
	}
	defer conn.Close()

	fmt.Println("✓ 成功连接到百度服务器")
	fmt.Printf("本地地址: %sn", conn.LocalAddr())
	fmt.Printf("远程地址: %sn", conn.RemoteAddr())

	// 发送HTTP请求
	request := "GET / HTTP/1.1rnHost: www.baidu.comrnrn"
	_, err = conn.Write([]byte(request))
	if err != nil {
		fmt.Printf("发送请求失败: %vn", err)
		return
	}

	// 读取响应头
	buffer := make([]byte, 1024)
	n, err := conn.Read(buffer)
	if err != nil {
		fmt.Printf("读取响应失败: %vn", err)
		return
	}

	fmt.Printf("收到响应 (%d 字节):n%sn", n, string(buffer[:200]))
}

// 练习1.2:ICMP程序实现(需要管理员权限)
func exercise1_2() {
	fmt.Println("n=== 练习1.2:ICMP程序实现 ===")

	// 题目:实现一个简单的ping程序
	// 注意:ICMP需要root权限,这里演示基本结构

	fmt.Println("ICMP程序结构演示(实际运行需要管理员权限):")
	fmt.Println(`
	conn, err := net.Dial("ip4:icmp", "www.google.com")
	if err != nil {
		log.Fatal("需要管理员权限:", err)
	}
	defer conn.Close()
	
	// 构造ICMP回显请求包
	data := []byte("Hello ICMP")
	_, err = conn.Write(data)
	if err != nil {
		log.Fatal("发送ICMP包失败:", err)
	}
	
	// 设置读取超时
	conn.SetReadDeadline(time.Now().Add(3 * time.Second))
	buffer := make([]byte, 1024)
	n, err := conn.Read(buffer)
	if err != nil {
		log.Fatal("读取ICMP响应失败:", err)
	}
	
	fmt.Printf("收到ICMP回复: %sn", string(buffer[:n]))
	`)
}

// 练习1.3:TCP客户端服务器实现
type TCPServer struct {
	listener net.Listener
	clients  map[string]net.Conn
}

func exercise1_3() {
	fmt.Println("n=== 练习1.3:TCP客户端服务器 ===")

	// 题目:实现一个TCP回声服务器和客户端

	// 启动服务器
	go func() {
		server := &TCPServer{
			clients: make(map[string]net.Conn),
		}
		server.start()
	}()

	// 等待服务器启动
	time.Sleep(100 * time.Millisecond)

	// 启动客户端
	tcpClient()
}

func (s *TCPServer) start() {
	var err error
	s.listener, err = net.Listen("tcp", ":8081")
	if err != nil {
		log.Printf("TCP服务器启动失败: %v", err)
		return
	}
	defer s.listener.Close()

	fmt.Println("✓ TCP服务器启动成功,监听端口 8081")

	for {
		conn, err := s.listener.Accept()
		if err != nil {
			log.Printf("接受连接失败: %v", err)
			continue
		}

		go s.handleClient(conn)
	}
}

func (s *TCPServer) handleClient(conn net.Conn) {
	defer conn.Close()
	clientAddr := conn.RemoteAddr().String()
	s.clients[clientAddr] = conn

	fmt.Printf("✓ 客户端连接: %sn", clientAddr)

	scanner := bufio.NewScanner(conn)
	for scanner.Scan() {
		message := scanner.Text()
		fmt.Printf("收到消息 [%s]: %sn", clientAddr, message)

		// 回声响应
		response := fmt.Sprintf("回声: %s", message)
		conn.Write([]byte(response + "n"))

		if message == "quit" {
			break
		}
	}

	delete(s.clients, clientAddr)
	fmt.Printf("✓ 客户端断开: %sn", clientAddr)
}

func tcpClient() {
	conn, err := net.Dial("tcp", "localhost:8081")
	if err != nil {
		fmt.Printf("连接服务器失败: %vn", err)
		return
	}
	defer conn.Close()

	fmt.Println("✓ 连接到TCP服务器成功")

	// 发送测试消息
	messages := []string{"Hello", "World", "Go语言", "quit"}

	for _, msg := range messages {
		// 发送消息
		_, err := conn.Write([]byte(msg + "n"))
		if err != nil {
			fmt.Printf("发送消息失败: %vn", err)
			break
		}

		// 读取响应
		buffer := make([]byte, 1024)
		n, err := conn.Read(buffer)
		if err != nil {
			fmt.Printf("读取响应失败: %vn", err)
			break
		}

		fmt.Printf("服务器响应: %s", string(buffer[:n]))
		time.Sleep(500 * time.Millisecond)
	}
}

// 练习1.4:UDP通信实现
func exercise1_4() {
	fmt.Println("n=== 练习1.4:UDP通信实现 ===")

	// 题目:实现UDP客户端和服务器通信

	// 启动UDP服务器
	go udpServer()
	time.Sleep(100 * time.Millisecond)

	// 启动UDP客户端
	udpClient()
}

func udpServer() {
	addr, err := net.ResolveUDPAddr("udp", ":8082")
	if err != nil {
		log.Printf("解析UDP地址失败: %v", err)
		return
	}

	conn, err := net.ListenUDP("udp", addr)
	if err != nil {
		log.Printf("UDP服务器启动失败: %v", err)
		return
	}
	defer conn.Close()

	fmt.Println("✓ UDP服务器启动成功,监听端口 8082")

	buffer := make([]byte, 1024)
	for i := 0; i < 3; i++ { // 只处理3个消息然后退出
		n, clientAddr, err := conn.ReadFromUDP(buffer)
		if err != nil {
			log.Printf("读取UDP消息失败: %v", err)
			continue
		}

		message := string(buffer[:n])
		fmt.Printf("收到UDP消息 [%s]: %sn", clientAddr, message)

		// 响应客户端
		response := fmt.Sprintf("UDP回声: %s", message)
		_, err = conn.WriteToUDP([]byte(response), clientAddr)
		if err != nil {
			log.Printf("发送UDP响应失败: %v", err)
		}
	}
}

func udpClient() {
	conn, err := net.Dial("udp", "localhost:8082")
	if err != nil {
		fmt.Printf("连接UDP服务器失败: %vn", err)
		return
	}
	defer conn.Close()

	fmt.Println("✓ 连接到UDP服务器成功")

	messages := []string{"UDP消息1", "UDP消息2", "UDP消息3"}

	for _, msg := range messages {
		// 发送消息
		_, err := conn.Write([]byte(msg))
		if err != nil {
			fmt.Printf("发送UDP消息失败: %vn", err)
			continue
		}

		// 读取响应
		buffer := make([]byte, 1024)
		n, err := conn.Read(buffer)
		if err != nil {
			fmt.Printf("读取UDP响应失败: %vn", err)
			continue
		}

		fmt.Printf("服务器响应: %sn", string(buffer[:n]))
		time.Sleep(200 * time.Millisecond)
	}
}

// ===========================================
// 第2章:HTTP编程练习
// ===========================================

// 练习2.1:HTTP客户端实现
func exercise2_1() {
	fmt.Println("n=== 练习2.1:HTTP客户端实现 ===")

	// 题目:实现HTTP GET和POST请求

	// GET请求
	fmt.Println("1. 执行HTTP GET请求:")
	resp, err := http.Get("https://h*ttp*bin.o*rg/get?param1=value1")
	if err != nil {
		fmt.Printf("GET请求失败: %vn", err)
		return
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("读取响应失败: %vn", err)
		return
	}

	fmt.Printf("✓ GET响应状态: %sn", resp.Status)
	fmt.Printf("响应内容(前200字符): %s...n", string(body[:min(200, len(body))]))

	// POST请求
	fmt.Println("n2. 执行HTTP POST请求:")
	postData := strings.NewReader(`{"name":"Go语言","type":"编程语言"}`)
	resp, err = http.Post("https://ht*tpb**in.org/post", "application/json", postData)
	if err != nil {
		fmt.Printf("POST请求失败: %vn", err)
		return
	}
	defer resp.Body.Close()

	body, err = io.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("读取POST响应失败: %vn", err)
		return
	}

	fmt.Printf("✓ POST响应状态: %sn", resp.Status)
	fmt.Printf("响应内容(前200字符): %s...n", string(body[:min(200, len(body))]))
	
}

// 练习2.2:HTTP服务器实现
func exercise2_2() {
	fmt.Println("n=== 练习2.2:HTTP服务器实现 ===")

	// 题目:实现一个功能完整的HTTP服务器

	mux := http.NewServeMux()

	// 根路径处理器
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		html := `
		
		
		Go HTTP服务器练习
		
			

欢迎来到Go HTTP服务器!

`
w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprint(w, html) }) // API路由 mux.HandleFunc("/api/users", usersHandler) mux.HandleFunc("/api/time", timeHandler) mux.HandleFunc("/form", formHandler) // 启动服务器 server := &http.Server{ Addr: ":8083", Handler: mux, } go func() { fmt.Println("✓ HTTP服务器启动成功,访问 http://local*host**:8083") if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Printf("HTTP服务器错误: %v", err) } }() // 测试客户端请求 time.Sleep(100 * time.Millisecond) testHTTPServer() } func usersHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": users := []map[string]interface{}{ {"id": 1, "name": "张三", "email": "zhangsan@example.com"}, {"id": 2, "name": "李四", "email": "lisi@example.com"}, } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(users) case "POST": var user map[string]interface{} if err := json.NewDecoder(r.Body).Decode(&user); err != nil { http.Error(w, "无效的JSON数据", http.StatusBadRequest) return } user["id"] = 3 // 模拟生成ID w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(user) default: http.Error(w, "方法不支持", http.StatusMethodNotAllowed) } } func timeHandler(w http.ResponseWriter, r *http.Request) { response := map[string]string{ "current_time": time.Now().Format("2006-01-02 15:04:05"), "timezone": "Asia/Shanghai", } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(response) } func formHandler(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { html := ` 表单测试

表单提交测试

姓名:

邮箱:

`
w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprint(w, html) } else if r.Method == "POST" { r.ParseForm() name := r.FormValue("name") email := r.FormValue("email") response := fmt.Sprintf(` 提交结果

表单提交成功!

姓名: %s

邮箱: %s

返回表单 `
, name, email) w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprint(w, response) } } func testHTTPServer() { fmt.Println("测试HTTP服务器:") // 测试GET请求 resp, err := http.Get("http://local*host**:8083/api/time") if err != nil { fmt.Printf("测试GET请求失败: %vn", err) return } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Printf("✓ GET /api/time 响应: %sn", string(body)) // 测试POST请求 postData := strings.NewReader(`{"name":"新用户","email":"newuser@example.com"}`) resp, err = http.Post("http://local*host**:8083/api/users", "application/json", postData) if err != nil { fmt.Printf("测试POST请求失败: %vn", err) return } defer resp.Body.Close() body, _ = io.ReadAll(resp.Body) fmt.Printf("✓ POST /api/users 响应: %sn", string(body)) } // =========================================== // 第3章:RPC编程练习 // =========================================== // 练习3.1:RPC服务实现 type Calculator struct{} type MathArgs struct { A, B float64 } type MathResult struct { Result float64 Error string } func (c *Calculator) Add(args *MathArgs, result *MathResult) error { result.Result = args.A + args.B return nil } func (c *Calculator) Subtract(args *MathArgs, result *MathResult) error { result.Result = args.A - args.B return nil } func (c *Calculator) Multiply(args *MathArgs, result *MathResult) error { result.Result = args.A * args.B return nil } func (c *Calculator) Divide(args *MathArgs, result *MathResult) error { if args.B == 0 { result.Error = "除数不能为零" return fmt.Errorf("division by zero") } result.Result = args.A / args.B return nil } func exercise3_1() { fmt.Println("n=== 练习3.1:RPC服务实现 ===") // 题目:实现一个RPC计算服务器 // 注册RPC服务 calc := new(Calculator) rpc.Register(calc) // 启动RPC服务器 go func() { listener, err := net.Listen("tcp", ":8084") if err != nil { log.Printf("RPC服务器启动失败: %v", err) return } defer listener.Close() fmt.Println("✓ RPC服务器启动成功,监听端口 8084") for { conn, err := listener.Accept() if err != nil { log.Printf("接受RPC连接失败: %v", err) continue } go rpc.ServeConn(conn) } }() // 等待服务器启动 time.Sleep(100 * time.Millisecond) // 测试RPC客户端 rpcClient() } func rpcClient() { client, err := rpc.Dial("tcp", "localhost:8084") if err != nil { fmt.Printf("连接RPC服务器失败: %vn", err) return } defer client.Close() fmt.Println("✓ 连接到RPC服务器成功") // 测试各种数学运算 tests := []struct { method string args MathArgs }{ {"Calculator.Add", MathArgs{10, 5}}, {"Calculator.Subtract", MathArgs{10, 3}}, {"Calculator.Multiply", MathArgs{4, 7}}, {"Calculator.Divide", MathArgs{20, 4}}, {"Calculator.Divide", MathArgs{10, 0}}, // 测试除零错误 } for _, test := range tests { var result MathResult err := client.Call(test.method, &test.args, &result) if err != nil { fmt.Printf("RPC调用失败 [%s]: %vn", test.method, err) } else if result.Error != "" { fmt.Printf("运算错误 [%s(%.1f, %.1f)]: %sn", test.method, test.args.A, test.args.B, result.Error) } else { fmt.Printf("✓ %s(%.1f, %.1f) = %.2fn", test.method, test.args.A, test.args.B, result.Result) } } } // 练习3.2:Gob编码实现 type Person struct { Name string Age int Email string Hobbies []string } func exercise3_2() { fmt.Println("n=== 练习3.2:Gob编码实现 ===") // 题目:使用Gob进行数据序列化和反序列化 // 原始数据 person := Person{ Name: "张三", Age: 28, Email: "zhangsan@example.com", Hobbies: []string{"编程", "阅读", "旅行"}, } fmt.Printf("原始数据: %+vn", person) // 编码 var buffer bytes.Buffer encoder := gob.NewEncoder(&buffer) err := encoder.Encode(person) if err != nil { fmt.Printf("Gob编码失败: %vn", err) return } fmt.Printf("✓ Gob编码成功,数据大小: %d 字节n", buffer.Len()) // 解码 decoder := gob.NewDecoder(&buffer) var decodedPerson Person err = decoder.Decode(&decodedPerson) if err != nil { fmt.Printf("Gob解码失败: %vn", err) return } fmt.Printf("✓ Gob解码成功: %+vn", decodedPerson) // 验证数据一致性 if person.Name == decodedPerson.Name && person.Age == decodedPerson.Age { fmt.Println("✓ 数据一致性验证通过") } else { fmt.Println("✗ 数据一致性验证失败") } } // 练习3.3:优雅的RPC接口设计 type UserService struct { users map[int]*User } type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email"` } type UserRequest struct { ID int `json:"id"` User User `json:"user"` } type UserResponse struct { Success bool `json:"success"` Message string `json:"message"` User *User `json:"user,omitempty"` Users []User `json:"users,omitempty"` } func NewUserService() *UserService { return &UserService{ users: map[int]*User{ 1: {ID: 1, Name: "张三", Email: "zhangsan@example.com"}, 2: {ID: 2, Name: "李四", Email: "lisi@example.com"}, }, } } func (s *UserService) GetUser(req *UserRequest, resp *UserResponse) error { if user, exists := s.users[req.ID]; exists { resp.Success = true resp.Message = "用户查询成功" resp.User = user } else { resp.Success = false resp.Message = fmt.Sprintf("用户不存在: ID=%d", req.ID) } return nil } func (s *UserService) CreateUser(req *UserRequest, resp *UserResponse) error { // 生成新ID newID := len(s.users) + 1 req.User.ID = newID s.users[newID] = &req.User resp.Success = true resp.Message = "用户创建成功" resp.User = &req.User return nil } func (s *UserService) ListUsers(req *UserRequest, resp *UserResponse) error { var users []User for _, user := range s.users { users = append(users, *user) } resp.Success = true resp.Message = fmt.Sprintf("查询到 %d 个用户", len(users)) resp.Users = users return nil } func exercise3_3() { fmt.Println("n=== 练习3.3:优雅的RPC接口设计 ===") // 题目:设计一个用户管理的RPC服务 // 注册服务 userService := NewUserService() rpc.Register(userService) // 启动服务器 go func() { listener, err := net.Listen("tcp", ":8085") if err != nil { log.Printf("用户服务RPC服务器启动失败: %v", err) return } defer listener.Close() fmt.Println("✓ 用户服务RPC服务器启动成功,监听端口 8085") for { conn, err := listener.Accept() if err != nil { continue } go rpc.ServeConn(conn) } }() time.Sleep(100 * time.Millisecond) // 测试客户端 userServiceClient() } func userServiceClient() { client, err := rpc.Dial("tcp", "localhost:8085") if err != nil { fmt.Printf("连接用户服务失败: %vn", err) return } defer client.Close() fmt.Println("✓ 连接到用户服务成功") // 测试获取用户 var resp UserResponse err = client.Call("UserService.GetUser", &UserRequest{ID: 1}, &resp) if err != nil { fmt.Printf("获取用户失败: %vn", err) } else { fmt.Printf("✓ 获取用户: %+vn", resp) } // 测试创建用户 newUser := User{Name: "王五", Email: "wangwu@example.com"} err = client.Call("UserService.CreateUser", &UserRequest{User: newUser}, &resp) if err != nil { fmt.Printf("创建用户失败: %vn", err) } else { fmt.Printf("✓ 创建用户: %+vn", resp) } // 测试列出所有用户 err = client.Call("UserService.ListUsers", &UserRequest{}, &resp) if err != nil { fmt.Printf("列出用户失败: %vn", err) } else { fmt.Printf("✓ 用户列表: %+vn", resp) } } // =========================================== // 第4章:JSON处理练习 // =========================================== // 练习4.1:JSON编码 type Product struct { ID int `json:"id"` Name string `json:"name"` Price float64 `json:"price"` Categories []string `json:"categories"` InStock bool `json:"in_stock"` CreatedTime string `json:"created_time"` } func exercise4_1() { fmt.Println("n=== 练习4.1:JSON编码 ===") // 题目:将Go结构体编码为JSON product := Product{ ID: 1001, Name: "Go语言编程指南", Price: 89.99, Categories: []string{"编程", "计算机", "Go语言"}, InStock: true, CreatedTime: time.Now().Format("2006-01-02 15:04:05"), } // 普通编码 jsonData, err := json.Marshal(product) if err != nil { fmt.Printf("JSON编码失败: %vn", err) return } fmt.Printf("✓ JSON编码结果:n%sn", string(jsonData)) // 美化编码 jsonPretty, err := json.MarshalIndent(product, "", " ") if err != nil { fmt.Printf("JSON美化编码失败: %vn", err) return } fmt.Printf("n✓ JSON美化编码结果:n%sn", string(jsonPretty)) } // 练习4.2:JSON解码 func exercise4_2() { fmt.Println("n=== 练习4.2:JSON解码 ===") // 题目:将JSON字符串解码为Go结构体 jsonStr := `{ "id": 2002, "name": "Python深度学习", "price": 128.50, "categories": ["人工智能", "深度学习", "Python"], "in_stock": false, "created_time": "2024-01-15 10:30:00" }` var product Product err := json.Unmarshal([]byte(jsonStr), &product) if err != nil { fmt.Printf("JSON解码失败: %vn", err) return } fmt.Printf("✓ JSON解码成功:n") fmt.Printf(" ID: %dn", product.ID) fmt.Printf(" 名称: %sn", product.Name) fmt.Printf(" 价格: %.2fn", product.Price) fmt.Printf(" 分类: %vn", product.Categories) fmt.Printf(" 库存: %tn", product.InStock) fmt.Printf(" 创建时间: %sn", product.CreatedTime) } // 练习4.3:解码未知结构的JSON func exercise4_3() { fmt.Println("n=== 练习4.3:解码未知结构的JSON ===") // 题目:处理动态JSON结构 jsonStr := `{ "user": { "name": "李明", "age": 30, "skills": ["Java", "Go", "Docker"], "address": { "country": "中国", "city": "北京", "postal_code": "100000" } }, "projects": [ { "name": "电商系统", "status": "完成", "team_size": 5 }, { "name": "微服务框架", "status": "进行中", "team_size": 3 } ], "metadata": { "version": "1.0", "last_updated": "2024-01-20" } }` var data map[string]interface{} err := json.Unmarshal([]byte(jsonStr), &data) if err != nil { fmt.Printf("JSON解码失败: %vn", err) return } fmt.Println("✓ 动态JSON解码成功:") // 处理用户信息 if user, ok := data["user"].(map[string]interface{}); ok { fmt.Printf("用户姓名: %sn", user["name"]) fmt.Printf("用户年龄: %.0fn", user["age"]) // 处理技能数组 if skills, ok := user["skills"].([]interface{}); ok { fmt.Print("技能: ") for i, skill := range skills { if i > 0 { fmt.Print(", ") } fmt.Print(skill) } fmt.Println() } // 处理嵌套地址对象 if address, ok := user["address"].(map[string]interface{}); ok { fmt.Printf("地址: %s %s %sn", address["country"], address["city"], address["postal_code"]) } } // 处理项目数组 if projects, ok := data["projects"].([]interface{}); ok { fmt.Printf("项目数量: %dn", len(projects)) for i, proj := range projects { if project, ok := proj.(map[string]interface{}); ok { fmt.Printf(" 项目%d: %s (状态: %s, 团队: %.0f人)n", i+1, project["name"], project["status"], project["team_size"]) } } } // 处理元数据 if metadata, ok := data["metadata"].(map[string]interface{}); ok { fmt.Printf("版本: %s, 更新时间: %sn", metadata["version"], metadata["last_updated"]) } } // 练习4.4:JSON流式读写 func exercise4_4() { fmt.Println("n=== 练习4.4:JSON流式读写 ===") // 题目:处理大量JSON数据的流式读写 // 模拟大量JSON数据 jsonStream := ` {"id":1,"name":"用户A","score":95.5} {"id":2,"name":"用户B","score":87.2} {"id":3,"name":"用户C","score":92.8} {"id":4,"name":"用户D","score":88.1} {"id":5,"name":"用户E","score":94.3} ` fmt.Println("✓ 流式解码JSON数据:") decoder := json.NewDecoder(strings.NewReader(jsonStream)) var totalScore float64 var userCount int for decoder.More() { var user map[string]interface{} err := decoder.Decode(&user) if err != nil { fmt.Printf("解码失败: %vn", err) continue } if score, ok := user["score"].(float64); ok { totalScore += score userCount++ } fmt.Printf(" 用户: %s, 分数: %.1fn", user["name"], user["score"]) } if userCount > 0 { avgScore := totalScore / float64(userCount) fmt.Printf("✓ 统计结果: %d个用户, 平均分数: %.2fn", userCount, avgScore) } // 流式编码示例 fmt.Println("n✓ 流式编码JSON数据:") var buffer bytes.Buffer encoder := json.NewEncoder(&buffer) users := []map[string]interface{}{ {"id": 6, "name": "新用户F", "score": 89.7}, {"id": 7, "name": "新用户G", "score": 93.1}, {"id": 8, "name": "新用户H", "score": 91.4}, } for _, user := range users { err := encoder.Encode(user) if err != nil { fmt.Printf("编码失败: %vn", err) continue } } fmt.Printf("编码结果:n%s", buffer.String()) } // =========================================== // 第5章:网站开发练习 // =========================================== // 练习5.1:最简单的网站程序 func exercise5_1() { fmt.Println("n=== 练习5.1:最简单的网站程序 ===") // 题目:创建一个基本的Web服务器 mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { html := fmt.Sprintf(` Go Web练习

? 欢迎来到Go Web世界!

当前时间: %s

请求方法: %s

请求路径: %s

用户代理: %s

导航

`
, time.Now().Format("2006-01-02 15:04:05"), r.Method, r.URL.Path, r.UserAgent()) w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprint(w, html) }) mux.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) { name := r.URL.Query().Get("name") if name == "" { name = "访客" } html := fmt.Sprintf(` 问候页面

你好, %s! ?

欢迎使用Go语言Web服务器!

返回首页 `
, name) w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprint(w, html) }) mux.HandleFunc("/info", func(w http.ResponseWriter, r *http.Request) { info := map[string]interface{}{ "server": "Go HTTP Server", "version": "1.0", "timestamp": time.Now().Unix(), "uptime": "运行中", } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(info) }) mux.HandleFunc("/api/status", func(w http.ResponseWriter, r *http.Request) { status := map[string]interface{}{ "status": "healthy", "message": "服务器运行正常", "time": time.Now().Format(time.RFC3339), } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(status) }) server := &http.Server{ Addr: ":8086", Handler: mux, } go func() { fmt.Println("✓ 简单Web服务器启动成功,访问 http://lo*ca*lho*st:8086") if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Printf("Web服务器错误: %v", err) } }() // 测试请求 time.Sleep(100 * time.Millisecond) testSimpleWebServer() } func testSimpleWebServer() { fmt.Println("测试简单Web服务器:") // 测试首页 resp, err := http.Get("http://lo*ca*lho*st:8086/") if err != nil { fmt.Printf("测试首页失败: %vn", err) return } resp.Body.Close() fmt.Printf("✓ 首页响应状态: %sn", resp.Status) // 测试API resp, err = http.Get("http://lo*ca*lho*st:8086/api/status") if err != nil { fmt.Printf("测试API失败: %vn", err) return } defer resp.Body.Close() var status map[string]interface{} json.NewDecoder(resp.Body).Decode(&status) fmt.Printf("✓ API状态: %sn", status["status"]) } // 练习5.2:net/http包深入使用 func exercise5_2() { fmt.Println("n=== 练习5.2:net/http包深入使用 ===") // 题目:实现中间件、路由和高级HTTP功能 mux := http.NewServeMux() // 静态文件服务器(模拟) mux.HandleFunc("/static/", func(w http.ResponseWriter, r *http.Request) { filename := strings.TrimPrefix(r.URL.Path, "/static/") content := fmt.Sprintf("这是静态文件: %s", filename) w.Header().Set("Content-Type", "text/plain") fmt.Fprint(w, content) }) // RESTful API mux.HandleFunc("/api/books", booksHandler) mux.HandleFunc("/api/books/", bookHandler) // 应用中间件 handler := loggingMiddleware(corsMiddleware(mux)) server := &http.Server{ Addr: ":8087", Handler: handler, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, } go func() { fmt.Println("✓ 高级HTTP服务器启动成功,访问 http://local*hos*t*:8087") if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Printf("高级HTTP服务器错误: %v", err) } }() time.Sleep(100 * time.Millisecond) testAdvancedWebServer() } // 中间件:日志记录 func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() next.ServeHTTP(w, r) fmt.Printf("? %s %s - %vn", r.Method, r.URL.Path, time.Since(start)) }) } // 中间件:CORS支持 func corsMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Content-Type") if r.Method == "OPTIONS" { w.WriteHeader(http.StatusOK) return } next.ServeHTTP(w, r) }) } type Book struct { ID int `json:"id"` Title string `json:"title"` Author string `json:"author"` Price float64 `json:"price"` } var books = []Book{ {1, "Go语言编程", "张三", 89.99}, {2, "微服务架构", "李四", 128.00}, {3, "云原生应用", "王五", 156.50}, } func booksHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(books) case "POST": var book Book if err := json.NewDecoder(r.Body).Decode(&book); err != nil { http.Error(w, "无效的JSON数据", http.StatusBadRequest) return } book.ID = len(books) + 1 books = append(books, book) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(book) default: http.Error(w, "方法不支持", http.StatusMethodNotAllowed) } } func bookHandler(w http.ResponseWriter, r *http.Request) { // 从URL中提取ID path := strings.TrimPrefix(r.URL.Path, "/api/books/") id, err := strconv.Atoi(path) if err != nil { http.Error(w, "无效的书籍ID", http.StatusBadRequest) return } // 查找书籍 var book *Book for i := range books { if books[i].ID == id { book = &books[i] break } } if book == nil { http.Error(w, "书籍不存在", http.StatusNotFound) return } switch r.Method { case "GET": w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(book) case "PUT": var updatedBook Book if err := json.NewDecoder(r.Body).Decode(&updatedBook); err != nil { http.Error(w, "无效的JSON数据", http.StatusBadRequest) return } updatedBook.ID = id *book = updatedBook w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(book) case "DELETE": // 删除书籍 for i := range books { if books[i].ID == id { books = append(books[:i], books[i+1:]...) break } } w.WriteHeader(http.StatusNoContent) default: http.Error(w, "方法不支持", http.StatusMethodNotAllowed) } } func testAdvancedWebServer() { fmt.Println("测试高级Web服务器:") // 测试GET所有书籍 resp, err := http.Get("http://local*hos*t*:8087/api/books") if err != nil { fmt.Printf("测试GET书籍列表失败: %vn", err) return } defer resp.Body.Close() var booksList []Book json.NewDecoder(resp.Body).Decode(&booksList) fmt.Printf("✓ 获取到 %d 本书籍n", len(booksList)) // 测试GET单本书籍 resp, err = http.Get("http://local*hos*t*:8087/api/books/1") if err != nil { fmt.Printf("测试GET单本书籍失败: %vn", err) return } defer resp.Body.Close() var book Book json.NewDecoder(resp.Body).Decode(&book) fmt.Printf("✓ 获取书籍: %sn", book.Title) } // 练习5.3:简单相册网站 type PhotoAlbum struct { Title string `json:"title"` Photos []Photo `json:"photos"` } type Photo struct { ID int `json:"id"` Title string `json:"title"` Filename string `json:"filename"` Caption string `json:"caption"` UploadTime string `json:"upload_time"` } var album = PhotoAlbum{ Title: "我的相册", Photos: []Photo{ {1, "风景照1", "landscape1.jpg", "美丽的山景", "2024-01-15 10:00:00"}, {2, "人物照1", "portrait1.jpg", "朋友聚会", "2024-01-16 14:30:00"}, {3, "风景照2", "landscape2.jpg", "海边日落", "2024-01-17 18:45:00"}, }, } func exercise5_3() { fmt.Println("n=== 练习5.3:简单相册网站 ===") // 题目:开发一个完整的相册网站 mux := http.NewServeMux() // 首页 - 相册展示 mux.HandleFunc("/", albumPageHandler) // 照片详情页 mux.HandleFunc("/photo/", photoDetailHandler) // 上传页面 mux.HandleFunc("/upload", uploadPageHandler) // API接口 mux.HandleFunc("/api/photos", photosAPIHandler) mux.HandleFunc("/api/upload", uploadAPIHandler) // 静态文件(模拟) mux.HandleFunc("/images/", imageHandler) server := &http.Server{ Addr: ":8088", Handler: mux, } go func() { fmt.Println("✓ 相册网站启动成功,访问 http://lo*c*alhos*t:8088") if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Printf("相册网站错误: %v", err) } }() time.Sleep(100 * time.Millisecond) testAlbumWebsite() } func albumPageHandler(w http.ResponseWriter, r *http.Request) { tmpl := ` {{.Title}}

? {{.Title}}

上传新照片
{{range .Photos}}
?️ {{.Filename}}
{{.Title}}
{{.Caption}}
{{.UploadTime}}
查看详情
{{end}}
`
t, err := template.New("album").Parse(tmpl) if err != nil { http.Error(w, "模板解析错误", http.StatusInternalServerError) return } w.Header().Set("Content-Type", "text/html; charset=utf-8") t.Execute(w, album) } func photoDetailHandler(w http.ResponseWriter, r *http.Request) { // 从URL中提取照片ID path := strings.TrimPrefix(r.URL.Path, "/photo/") id, err := strconv.Atoi(path) if err != nil { http.Error(w, "无效的照片ID", http.StatusBadRequest) return } // 查找照片 var photo *Photo for i := range album.Photos { if album.Photos[i].ID == id { photo = &album.Photos[i] break } } if photo == nil { http.Error(w, "照片不存在", http.StatusNotFound) return } tmpl := ` {{.Title}} - 照片详情

{{.Title}}

?️ {{.Filename}}

标题: {{.Title}}

描述: {{.Caption}}

文件名: {{.Filename}}

上传时间: {{.UploadTime}}

返回相册
`
t, err := template.New("photo").Parse(tmpl) if err != nil { http.Error(w, "模板解析错误", http.StatusInternalServerError) return } w.Header().Set("Content-Type", "text/html; charset=utf-8") t.Execute(w, photo) } func uploadPageHandler(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { // 处理表单提交 title := r.FormValue("title") caption := r.FormValue("caption") if title == "" { http.Error(w, "照片标题不能为空", http.StatusBadRequest) return } // 创建新照片 newPhoto := Photo{ ID: len(album.Photos) + 1, Title: title, Filename: fmt.Sprintf("photo_%d.jpg", len(album.Photos)+1), Caption: caption, UploadTime: time.Now().Format("2006-01-02 15:04:05"), } album.Photos = append(album.Photos, newPhoto) // 重定向到首页 http.Redirect(w, r, "/", http.StatusSeeOther) return } // 显示上传表单 uploadForm := ` 上传照片

? 上传新照片

返回相册
`
w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprint(w, uploadForm) } func photosAPIHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(album) default: http.Error(w, "方法不支持", http.StatusMethodNotAllowed) } } func uploadAPIHandler(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { http.Error(w, "方法不支持", http.StatusMethodNotAllowed) return } var photo Photo if err := json.NewDecoder(r.Body).Decode(&photo); err != nil { http.Error(w, "无效的JSON数据", http.StatusBadRequest) return } photo.ID = len(album.Photos) + 1 photo.UploadTime = time.Now().Format("2006-01-02 15:04:05") album.Photos = append(album.Photos, photo) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(photo) } func imageHandler(w http.ResponseWriter, r *http.Request) { // 模拟图片服务 filename := strings.TrimPrefix(r.URL.Path, "/images/") w.Header().Set("Content-Type", "text/plain") fmt.Fprintf(w, "这里应该是图片文件: %s", filename) } func testAlbumWebsite() { fmt.Println("测试相册网站:") // 测试获取相册 resp, err := http.Get("http://lo*c*alhos*t:8088/api/photos") if err != nil { fmt.Printf("测试相册API失败: %vn", err) return } defer resp.Body.Close() var albumData PhotoAlbum json.NewDecoder(resp.Body).Decode(&albumData) fmt.Printf("✓ 相册包含 %d 张照片n", len(albumData.Photos)) // 测试照片详情 resp, err = http.Get("http://lo*c*alhos*t:8088/photo/1") if err != nil { fmt.Printf("测试照片详情失败: %vn", err) return } resp.Body.Close() fmt.Printf("✓ 照片详情页响应状态: %sn", resp.Status) } // =========================================== // 工具函数 // =========================================== func min(a, b int) int { if a < b { return a } return b } // =========================================== // 主函数 - 执行所有练习 // =========================================== func main() { fmt.Println("? Go语言网络编程练习题集") fmt.Println("=========================================") // 第1章:Socket编程练习 fmt.Println("n? 第1章:Socket编程练习") exercise1_1() exercise1_2() exercise1_3() exercise1_4() // 第2章:HTTP编程练习 fmt.Println("n? 第2章:HTTP编程练习") exercise2_1() exercise2_2() // 第3章:RPC编程练习 fmt.Println("n? 第3章:RPC编程练习") exercise3_1() exercise3_2() exercise3_3() // 第4章:JSON处理练习 fmt.Println("n? 第4章:JSON处理练习") exercise4_1() exercise4_2() exercise4_3() exercise4_4() // 第5章:网站开发练习 fmt.Println("n? 第5章:网站开发练习") exercise5_1() exercise5_2() exercise5_3() fmt.Println("n? 所有练习执行完成!") fmt.Println("=========================================") fmt.Println("? 练习总结:") fmt.Println("1. Socket编程: 掌握了TCP/UDP通信和网络连接") fmt.Println("2. HTTP编程: 学会了HTTP客户端和服务端开发") fmt.Println("3. RPC编程: 理解了远程过程调用和Gob序列化") fmt.Println("4. JSON处理: 熟练掌握JSON编解码和流式处理") fmt.Println("5. 网站开发: 能够开发完整的Web应用程序") fmt.Println("n? 建议:") fmt.Println("- 每个练习都要亲自运行和修改代码") fmt.Println("- 尝试扩展功能,如添加错误处理、日志记录等") fmt.Println("- 结合实际项目需求,应用所学知识") fmt.Println("- 关注性能优化和安全性问题") // 保持程序运行一段时间以便测试Web服务器 fmt.Println("n⏰ Web服务器将继续运行30秒供您测试...") time.Sleep(30 * time.Second) fmt.Println("✅ 练习程序结束") } /* =========================================== 运行说明 =========================================== 1. 编译运行: go run network_programming_exercises.go 2. 测试Web服务器: - 简单Web服务器: http://lo*ca*lho*st:8086 - HTTP服务器: http://local*host**:8083 - 高级HTTP服务器: http://local*hos*t*:8087 - 相册网站: http://lo*c*alhos*t:8088 3. 注意事项: - 确保端口8081-8088没有被占用 - ICMP功能需要管理员权限 - 某些防火墙可能阻止网络连接 4. 扩展练习: - 添加数据库支持 - 实现用户认证 - 添加文件上传功能 - 实现WebSocket通信 - 添加缓存机制 =========================================== */