Go语言实战案例:用net/http构建一个RESTful API

Go 的标准库 net/http 提供了构建 Web 服务所需的强大功能。虽然众多第三方框架(如 Gin、Echo)已经封装了很多功能,但如果你真正想理解 Go 的底层 Web 服务机制,那么使用 net/http 实现一个原生的 RESTful API 是最好的入门方式。

本文将通过一个实战案例:构建一个用户信息管理 API,带你从零开始打造 RESTful 服务。


一、什么是 RESTful API?

REST(Representational State Transfer)是一种软件架构风格,常用于 Web API 的设计。

常见 HTTP 方法与操作语义:

方法 语义 说明
GET 获取资源 读取某个资源的内容
POST 创建资源 向服务器添加新资源
PUT 更新资源 修改已有资源
DELETE 删除资源 移除某个资源

二、实战目标:用户信息管理 API

我们将构建以下功能的 API:

  • GET /users:获取用户列表
  • GET /users/{id}:获取指定用户
  • POST /users:创建新用户
  • PUT /users/{id}:更新用户
  • DELETE /users/{id}:删除用户

三、代码实现

1. 用户数据结构

go 复制代码
package main

import (
    "encoding/json"
    "fmt"
    "log"
    "math/rand"
    "net/http"
    "strconv"
    "strings"
    "sync"
)

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
    Age  int    `json:"age"`
}

var (
    users   = make(map[int]User)
    mu      sync.Mutex
)

2. 工具函数:ID提取

go 复制代码
func parseID(path string) (int, error) {
    parts := strings.Split(path, "/")
    if len(parts) < 3 {
        return 0, fmt.Errorf("invalid path")
    }
    return strconv.Atoi(parts[2])
}

3. 处理函数

scss 复制代码
func usersHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")

    switch r.Method {
    case "GET":
        // 获取所有用户
        mu.Lock()
        list := make([]User, 0, len(users))
        for _, user := range users {
            list = append(list, user)
        }
        mu.Unlock()
        json.NewEncoder(w).Encode(list)

    case "POST":
        // 创建用户
        var user User
        if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }
        user.ID = rand.Intn(10000)
        mu.Lock()
        users[user.ID] = user
        mu.Unlock()
        json.NewEncoder(w).Encode(user)

    default:
        http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
    }
}
scss 复制代码
func userHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")

    id, err := parseID(r.URL.Path)
    if err != nil {
        http.Error(w, "Invalid ID", http.StatusBadRequest)
        return
    }

    mu.Lock()
    user, exists := users[id]
    mu.Unlock()

    switch r.Method {
    case "GET":
        if !exists {
            http.NotFound(w, r)
            return
        }
        json.NewEncoder(w).Encode(user)

    case "PUT":
        if !exists {
            http.NotFound(w, r)
            return
        }
        var updated User
        if err := json.NewDecoder(r.Body).Decode(&updated); err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }
        updated.ID = id
        mu.Lock()
        users[id] = updated
        mu.Unlock()
        json.NewEncoder(w).Encode(updated)

    case "DELETE":
        if !exists {
            http.NotFound(w, r)
            return
        }
        mu.Lock()
        delete(users, id)
        mu.Unlock()
        w.WriteHeader(http.StatusNoContent)

    default:
        http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
    }
}

4. 主函数启动服务

go 复制代码
func main() {
    http.HandleFunc("/users", usersHandler)
    http.HandleFunc("/users/", userHandler)

    fmt.Println("服务启动中: http://localhost:8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

四、测试方式(推荐使用 curl 或 Postman)

bash 复制代码
# 创建用户
curl -X POST -H "Content-Type: application/json" \
     -d '{"name":"Tom","age":25}' http://localhost:8080/users

# 获取所有用户
curl http://localhost:8080/users

# 获取指定用户
curl http://localhost:8080/users/1234

# 更新用户
curl -X PUT -H "Content-Type: application/json" \
     -d '{"name":"Jerry","age":30}' http://localhost:8080/users/1234

# 删除用户
curl -X DELETE http://localhost:8080/users/1234

五、总结与建议

通过本案例,我们学习了如何用 Go 原生的 net/http

✅ 实现 RESTful 风格的接口

✅ 处理不同的 HTTP 方法

✅ 编解码 JSON 数据

✅ 线程安全地管理数据结构

虽然这个例子是最基础的,但它奠定了你进一步使用更强大框架(如 Gin、Echo)的基础。


六、进阶推荐

  • • 加入中间件(如日志、认证)
  • • 使用 context 处理请求生命周期
  • • 支持 URL 参数和 Query 参数
  • • 使用第三方路由库如 gorilla/mux
  • • 数据存储替换为数据库(如 GORM + MySQL)
相关推荐
㳺三才人子6 小时前
初探 Flask
后端·python·flask·html
星栈独行6 小时前
我在 Rust 全栈项目里用 JWT 做无状态认证
开发语言·后端·rust·前端框架·开源·github·web
Java爱好狂.7 小时前
Java程序员体系化学习路线(2026最新版)
java·后端·java面试·java架构师·java程序员·java八股文·java学习路线
陈随易7 小时前
Redis 8.8发布,一定要更新
前端·后端·程序员
装不满的克莱因瓶7 小时前
SpringBoot 如何将 lib 目录中jar包打包进最终的jar包里面
spring boot·后端·maven·jar·mvn
ltl8 小时前
Transformer 原论文实验结果:为什么 28.4 BLEU 足以改写路线图
后端
excel9 小时前
为什么我推荐使用 Termius:现代 SSH 工具的完整体验
前端·后端
卷毛的技术笔记9 小时前
Java后端硬核实战:用Spring AI Alibaba+Redis给LLM装上“超强记忆中枢”
java·人工智能·redis·后端·spring·ai·系统架构
IT_陈寒10 小时前
Java的Optional差点让我掉坑里,这几个坑你别踩
前端·人工智能·后端
子兮曰11 小时前
Harness 驾驭工程深度教程:从 AGENTS.md 到全链路 AI 编码基础设施
前端·后端·ai编程