Go 入门(26):练习——HTTP 接口服务
更新时间:2026-09-01。本文是
languages/go/beginner/入门层第 26 篇,接 CLI 待办事项。综合练习写一个 HTTP 接口服务,用户管理 CRUD,数据存在内存里。用 Go 标准库 net/http,不加第三方框架。
需求
实现一个用户管理 RESTful 接口:
| 方法 | 路径 | 功能 |
|---|---|---|
| GET | /users | 列出所有用户 |
| GET | /users/{id} | 查询单个用户 |
| POST | /users | 创建用户 |
| DELETE | /users/{id} | 删除用户 |
数据存在内存中(map[string]User)。
用到的知识
net/http包启动 HTTP 服务encoding/json序列化请求和响应io.ReadAll读取请求体strings包处理 URL 路径- 结构体组织数据
实现
go
package main
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"strings"
)
type User struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
var users = make(map[string]User)
func main() {
// 初始数据
users["1"] = User{ID: "1", Name: "Alice", Email: "alice@example.com"}
users["2"] = User{ID: "2", Name: "Bob", Email: "bob@example.com"}
http.HandleFunc("/users", usersHandler)
http.HandleFunc("/users/", userHandler)
log.Println("Server starting on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
// GET /users - 列出所有用户
// POST /users - 创建用户
func usersHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
userList := make([]User, 0, len(users))
for _, u := range users {
userList = append(userList, u)
}
writeJSON(w, http.StatusOK, userList)
case http.MethodPost:
body, err := io.ReadAll(r.Body)
if err != nil {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid body"})
return
}
var u User
if err := json.Unmarshal(body, &u); err != nil {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid json"})
return
}
if u.ID == "" {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "id required"})
return
}
users[u.ID] = u
writeJSON(w, http.StatusCreated, u)
default:
writeJSON(w, http.StatusMethodNotAllowed, map[string]string{"error": "method not allowed"})
}
}
// GET /users/{id} - 查询单个用户
// DELETE /users/{id} - 删除用户
func userHandler(w http.ResponseWriter, r *http.Request) {
id := strings.TrimPrefix(r.URL.Path, "/users/")
if id == "" {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "id required"})
return
}
switch r.Method {
case http.MethodGet:
u, ok := users[id]
if !ok {
writeJSON(w, http.StatusNotFound, map[string]string{"error": "user not found"})
return
}
writeJSON(w, http.StatusOK, u)
case http.MethodDelete:
_, ok := users[id]
if !ok {
writeJSON(w, http.StatusNotFound, map[string]string{"error": "user not found"})
return
}
delete(users, id)
writeJSON(w, http.StatusNoContent, nil)
default:
writeJSON(w, http.StatusMethodNotAllowed, map[string]string{"error": "method not allowed"})
}
}
func writeJSON(w http.ResponseWriter, status int, data any) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
if data != nil {
json.NewEncoder(w).Encode(data)
}
}运行和测试
bash
go run main.go
# 另一个终端测试
curl http://localhost:8080/users
# [{"id":"1","name":"Alice","email":"alice@example.com"},...]
curl http://localhost:8080/users/1
# {"id":"1","name":"Alice","email":"alice@example.com"}
curl -X POST http://localhost:8080/users \
-d '{"id":"3","name":"Charlie","email":"charlie@example.com"}'
# 201 Created
curl -X DELETE http://localhost:8080/users/3
# 204 No Content扩展练习
- 支持 PUT 更新用户
- 改成文件持久化,重启后数据不丢失
- 加一个中间件:打印每个请求的 Method、Path、耗时
- 用结构体抽取写 response 的通用逻辑
相关与延伸
下一篇:练习:并发爬虫;net/http 底层是 goroutine-per-request 模型,每个请求开一个 goroutine 处理;Go 标准库的 HTTP 服务已经够用,进阶层讲中间件。
一句话总结
HTTP 接口服务:用 net/http 标准库就能写 RESTful 接口,http.HandleFunc 注册路由,r.Method 判断方法分发,json.NewEncoder/Decoder 处理 JSON 序列化;Go 标准库不依赖第三方框架就能写生产级服务。