引言:为什么Go是REST API的理想选择
Go(又称Golang)是Google开发的一种编译型编程语言,兼具C++的性能和Python的简洁性。如果您想构建一个快速、可靠且易于维护的REST API,Go是最佳选择之一。在本文中,我们将在30分钟内用Go编写一个完整的REST API,支持创建、读取、更新和删除记录(CRUD)。无需复杂的框架——仅使用标准库net/http和少量代码。
文章结束时,您将获得一个可用的HTTP服务器,能够以JSON格式响应请求,且无需外部依赖。让我们开始吧!
步骤1:项目设置与结构
首先,确保您已安装Go(版本1.16+)。创建一个新项目目录并初始化模块:
mkdir go-rest-apicd go-rest-apigo mod init go-rest-api项目结构很简单——只有一个main.go文件。我们将所有代码放在其中,以免使示例复杂化。在实际项目中,您当然会将代码拆分为多个包,但对于学习来说,这是理想的方式。
步骤2:定义数据结构与全局存储
我们的API将管理一个图书列表。创建一个Book结构体和一个简单的切片用于在内存中存储数据(代替数据库)。
package main
import ( "encoding/json" "log" "net/http" "strconv" "strings")
type Book struct { ID int `json:"id"` Title string `json:"title"` Author string `json:"author"` Year int `json:"year"`}
var books []Bookvar nextID int = 1这里books是我们的临时“数据层”,nextID是用于自动为新书分配ID的计数器。
步骤3:实现HTTP请求处理器(CRUD)
现在是最有趣的部分——为每个HTTP方法编写处理器函数。我们将使用标准路由器http.NewServeMux。
3.1. 获取所有图书(GET /books)
func getBooks(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(books)}3.2. 创建新图书(POST /books)
func createBook(w http.ResponseWriter, r *http.Request) { var newBook Book if err := json.NewDecoder(r.Body).Decode(&newBook); err != nil { http.Error(w, "Invalid JSON", http.StatusBadRequest) return } newBook.ID = nextID nextID++ books = append(books, newBook) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(newBook)}3.3. 根据ID获取单本图书(GET /books/{id})
标准ServeMux不支持动态路径,因此我们将手动从URL中提取ID。
func getBook(w http.ResponseWriter, r *http.Request) { idStr := strings.TrimPrefix(r.URL.Path, "/books/") id, err := strconv.Atoi(idStr) if err != nil { http.Error(w, "Invalid ID", http.StatusBadRequest) return } for _, book := range books { if book.ID == id { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(book) return } } http.Error(w, "Book not found", http.StatusNotFound)}3.4. 更新图书(PUT /books/{id})
func updateBook(w http.ResponseWriter, r *http.Request) { idStr := strings.TrimPrefix(r.URL.Path, "/books/") id, err := strconv.Atoi(idStr) if err != nil { http.Error(w, "Invalid ID", http.StatusBadRequest) return } var updatedBook Book if err := json.NewDecoder(r.Body).Decode(&updatedBook); err != nil { h