在Golang中构建REST API - Bastian Isensee
REST API 是当今分布式软件系统中最常见的架构模式之一。本文将为您概述 REST 的基本概念,并通过一个用 Golang 编写的示例 API 展示其实现方式。
什么是 REST API?
- API(应用程序编程接口)是软件组件之间的桥梁,允许不同部分的系统进行通信和交互。
- REST 代表“表述性状态转移”(Representational State Transfer),是一种设计 API 的风格,用于通过网络在分布式应用程序之间进行通信。
- REST API 广泛应用于各种规模的软件系统中,从简单的 Web 或移动应用程序到复杂的分布式微服务架构。
- REST 通信是同步的,通常用于需要快速响应的场景,例如在用户界面中显示数据。
- 在某些情况下,异步架构可能更适合,例如数据需要分发到多个服务或数据处理耗时较长时。
- REST 的数据交换是语言无关的,这使其能够与多种软件系统兼容。通常,仅需基本的 HTTP 和数据序列化功能即可实现。
REST API 的构建块
- 服务器与客户端:通信发生在提供 REST API 的服务器和与之交互的客户端之间。
- HTTP 协议:虽然 REST 不强制使用 HTTP,但 HTTP 是最常用的底层协议,因此通常需要一个 HTTP 服务器。
- 资源与操作:REST API 的核心是资源,资源通过 HTTP 方法 和 URL 路径 来描述操作。
- 数据序列化:REST 是为网络通信设计的,因此需要对数据进行序列化。最常用的格式是 JSON,因为它简单且易于阅读。
示例:Todo 列表 API
为了更好地说明,我们将实现一个用 Golang 编写的简单 REST API。我们的资源是 Todo 项目,它描述了一项任务,可以标记为已完成或未完成。
API 端点设计
-
获取所有 Todo 项目:
- 请求:
GET /Todo/all - 操作:只读操作,不会修改服务器端状态。
- 请求:
-
添加新的 Todo 项目:
- 请求:
POST /Todo - 操作:通过 HTTP 请求体传输新的 Todo 项目,创建一个新的资源。
- 请求:
-
操作特定的 Todo 项目:
- 获取特定项目:
GET /Todo/{index},只读操作。 - 更新特定项目:
PUT /Todo/{index},通过 HTTP 请求体传输更新的 Todo 项目,替换现有资源。PUT 操作是幂等的。 - 删除特定项目:
DELETE /Todo/{index},删除指定资源。
- 获取特定项目:
Golang 中的实现
启动 HTTP 服务器
在 Golang 中启动一个 HTTP 服务器非常简单。以下是一个定义简单端点 /hello 的示例:
package main
import (
"fmt"
"net/http"
)func main() {
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, World!")
})
http.ListenAndServe(":8080", nil)
}
运行程序后,可以通过浏览器或 [curl](https://www.explinks.com/wiki/what-are-curl-url-uri/) 查询 /hello 端点。
请求处理
为了更灵活地处理请求,可以使用 Golang 的 ServeMux 类型。ServeMux 是一个多路复用器,通过 URL 路径和 HTTP 方法将请求分派到具体的处理逻辑中。
数据模型
以下是一个简单的 Todo 数据模型示例:
type Todo struct {
Title string json:"title"
Completed bool json:"completed"
}
需要注意的是,只有导出的字段(以大写字母开头)才能被序列化为 JSON 或从 JSON 反序列化。
读写 JSON 数据
Golang 提供了标准库函数 json.Marshal 和 json.Unmarshal 来处理 JSON 数据。例如:
- 将 Go 类型写入 HTTP 响应:
todos := []Todo{{Title: "Learn Go", Completed: false}}
jsonData, _ := json.Marshal(todos)
w.Write(jsonData)
- 从请求体中读取 JSON 数据:
var todo Todo
json.NewDecoder(r.Body).Decode(&todo)
URL 参数与查询参数
- URL 参数:通过路径参数(如
/Todo/{index})获取特定资源。 - 查询参数:通过
GET /Todo/all?complete=false只返回未完成的任务。
状态代码与错误处理
为客户端提供有意义的状态代码和错误消息是 REST API 的重要部分。例如:
- 设置状态代码
201 Created:
w.WriteHeader(http.StatusCreated)
- 返回错误状态和消息:
http.Error(w, "Invalid data", http.StatusBadRequest)
总结
通过以上构建块,我们在 Golang 中实现了一个简单但功能强大的 REST API。整个过程完全基于标准库,无需第三方依赖。Golang 提供了直观且高效的工具来构建 REST API,这在许多其他语言中可能更为复杂。
REST API 的核心概念已经在本文中详细讨论。如果您对完整的源代码(包括自动化测试)感兴趣,可以参考相关代码仓库。
原文链接: https://bastian-isensee.com/post/29-rest-api-go/