当前位置: 首页 > news >正文

15分钟学 Go 第 42 天:RESTful API设计

第42天:RESTful API设计

目标:理解RESTful API的设计原则

在现代Web开发中,RESTful API(Representational State Transfer)已经成为了标准的架构风格,用于实现客户端与服务器之间的通信。通过遵循REST的设计原则,我们能够构建简洁、高效、可维护的API接口。今天,我们将深入理解RESTful API的设计原则,并通过实际代码示例来学习如何在Go语言中实现这些设计。

本节内容将涵盖以下几个方面:

  1. RESTful API概述
  2. RESTful设计的核心原则
  3. Go语言实现RESTful API
  4. 常见的RESTful API设计示例
  5. Go语言中的HTTP请求和响应处理
  6. RESTful API设计流程图
  7. 总结

1. RESTful API概述

RESTful API是一种Web API设计风格,它通过HTTP协议进行客户端和服务器之间的数据交换。RESTful API使用标准的HTTP方法(如GETPOSTPUTDELETE)来操作资源,资源通过URL进行标识,数据通常以JSON或XML格式进行传输。

关键概念:

  • 资源(Resource):在RESTful架构中,资源代表了可被操作的数据实体,通常以URL的形式暴露给客户端。
  • HTTP动词(Verb):用于操作资源的HTTP方法。常见的动词包括:
    • GET:获取资源。
    • POST:创建资源。
    • PUT:更新资源。
    • DELETE:删除资源。
  • 状态(State):每次客户端请求都会根据当前的状态返回相应的资源。

RESTful API的基本特点:

  • 无状态性(Stateless):每个请求都是独立的,服务器不会保存任何客户端的状态信息。
  • 统一接口(Uniform Interface):所有的API请求和响应都遵循统一的约定和规则,使得API更容易理解和使用。
  • 层次系统(Layered System):客户端通过代理与服务器进行通信,服务器之间可能会有多个层次。

2. RESTful设计的核心原则

在设计RESTful API时,有一系列的设计原则需要遵循,以下是最重要的几个原则:

2.1. 使用HTTP动词来操作资源

RESTful API推荐使用标准的HTTP动词来表示对资源的操作:

  • GET:用于检索资源。
  • POST:用于创建资源。
  • PUT:用于更新资源。
  • DELETE:用于删除资源。

例子:
假设我们有一个关于“用户”的资源,使用这些HTTP动词进行操作:

  • GET /users:获取所有用户。
  • POST /users:创建新用户。
  • GET /users/{id}:获取指定ID的用户信息。
  • PUT /users/{id}:更新指定ID的用户信息。
  • DELETE /users/{id}:删除指定ID的用户。

2.2. 使用URL表示资源

在RESTful架构中,资源应该通过URL进行标识,URL应具备唯一性和语义性。例如:

  • /users 表示用户资源。
  • /products 表示产品资源。

例子:

  • /users:表示所有用户。
  • /users/{id}:表示特定ID的用户。
  • /orders/{orderId}/items:表示特定订单的所有商品项。

2.3. 无状态性

每个请求必须包含完成该请求所需的所有信息(如认证信息、请求数据等)。服务器不应存储客户端的状态,保证每次请求都是独立的。

2.4. 支持多种格式的数据交换

虽然JSON是最常用的格式,但RESTful API应该支持多种数据格式,如XML、HTML等,客户端可以通过Accept头来请求不同的数据格式。


3. Go语言实现RESTful API

Go语言本身有强大的内建HTTP库,可以非常方便地实现RESTful API。在Go中,我们通常使用net/http包来处理HTTP请求和响应。

3.1 实现简单的RESTful API

我们从一个简单的用户管理API开始,展示如何使用Go语言实现RESTful接口。

例子代码:

package mainimport ("encoding/json""fmt""log""net/http""github.com/gorilla/mux"
)// 定义用户结构体
type User struct {ID   string `json:"id"`Name string `json:"name"`Age  int    `json:"age"`
}// 模拟数据库
var users = []User{{ID: "1", Name: "Alice", Age: 30},{ID: "2", Name: "Bob", Age: 25},
}// 获取所有用户的处理函数
func getUsers(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json")json.NewEncoder(w).Encode(users)
}// 获取指定用户的处理函数
func getUser(w http.ResponseWriter, r *http.Request) {params := mux.Vars(r)for _, user := range users {if user.ID == params["id"] {w.Header().Set("Content-Type", "application/json")json.NewEncoder(w).Encode(user)return}}http.Error(w, "User not found", http.StatusNotFound)
}// 创建新用户的处理函数
func createUser(w http.ResponseWriter, r *http.Request) {var newUser Userdecoder := json.NewDecoder(r.Body)if err := decoder.Decode(&newUser); err != nil {http.Error(w, err.Error(), http.StatusBadRequest)return}users = append(users, newUser)w.Header().Set("Content-Type", "application/json")json.NewEncoder(w).Encode(newUser)
}// 更新用户的处理函数
func updateUser(w http.ResponseWriter, r *http.Request) {params := mux.Vars(r)var updatedUser Userdecoder := json.NewDecoder(r.Body)if err := decoder.Decode(&updatedUser); err != nil {http.Error(w, err.Error(), http.StatusBadRequest)return}for index, user := range users {if user.ID == params["id"] {users[index] = updatedUserw.Header().Set("Content-Type", "application/json")json.NewEncoder(w).Encode(updatedUser)return}}http.Error(w, "User not found", http.StatusNotFound)
}// 删除用户的处理函数
func deleteUser(w http.ResponseWriter, r *http.Request) {params := mux.Vars(r)for index, user := range users {if user.ID == params["id"] {users = append(users[:index], users[index+1:]...)w.WriteHeader(http.StatusNoContent)return}}http.Error(w, "User not found", http.StatusNotFound)
}func main() {r := mux.NewRouter()// 注册RESTful路由r.HandleFunc("/users", getUsers).Methods("GET")r.HandleFunc("/users/{id}", getUser).Methods("GET")r.HandleFunc("/users", createUser).Methods("POST")r.HandleFunc("/users/{id}", updateUser).Methods("PUT")r.HandleFunc("/users/{id}", deleteUser).Methods("DELETE")// 启动HTTP服务器log.Fatal(http.ListenAndServe(":8080", r))
}

代码解析

  • 我们首先定义了一个User结构体来表示用户资源。
  • 使用mux路由器来处理不同的HTTP方法和路径映射。
  • 实现了五个常见的API操作:GET(获取所有用户)、GET/{id}(获取特定用户)、POST(创建新用户)、PUT/{id}(更新用户信息)、DELETE/{id}(删除用户)。
  • 使用json.NewEncoder(w).Encode()将Go的结构体编码为JSON格式并返回给客户端。

启动服务

运行上述代码后,API会在本地的8080端口启动。你可以使用curl或Postman等工具进行请求测试。例如:

  • GET请求:获取所有用户

    curl http://localhost:8080/users
    
  • POST请求:创建新用户

    curl -X POST -H "Content-Type: application/json" -d '{"id":"3", "name":"Charlie", "age":28}' http://localhost:8080/users
    

4. 常见的RESTful API设计示例

4.1. 用户管理API

API设计应该尽量简单和直观,常见的用户管理API包括以下操作:

  • GET /users:获取所有用户。
  • GET /users/{id}:获取指定用户的信息。
  • POST /users:创建一个新的用户。
  • PUT /users/{id}:更新指定用户的信息。
  • DELETE /users/{id}:删除指定用户。

4.2. 商品管理API

类似地,商品管理API的设计可能如下:

  • GET /products:获取所有商品。

GET /products/{id}:获取指定商品的详情。

  • POST /products:创建新商品。
  • PUT /products/{id}:更新商品信息。
  • DELETE /products/{id}:删除商品。

4.3. 订单管理API

订单管理API的设计:

  • GET /orders:获取所有订单。
  • GET /orders/{id}:获取指定订单的详情。
  • POST /orders:创建订单。
  • PUT /orders/{id}:更新订单信息。
  • DELETE /orders/{id}:取消订单。

5. RESTful API设计流程图

以下是一个简单的RESTful API请求和响应的流程图:

┌───────────────────────┐
│   客户端发起请求        │
└───────────────────────┘│▼┌─────────────────────┐│  API路由器解析请求    │└─────────────────────┘│▼┌──────────────────┐│  匹配请求的资源    │└──────────────────┘│▼┌──────────────────┐│  调用相应处理器    │└──────────────────┘│▼┌────────────────┐│ 处理请求并生成响应│└────────────────┘│▼┌────────────────┐│ 返回响应给客户端  │└────────────────┘

总结

今天我们深入了解了RESTful API的设计原则,并通过实际的Go语言示例实现了一个简单的用户管理API。通过学习,我们掌握了如何设计符合RESTful规范的API接口,如何使用Go语言的net/http包和mux路由器来实现这些API操作。掌握这些基础后,你可以在项目中灵活应用这些原则,设计和开发高效、易于维护的API。


怎么样今天的内容还满意吗?再次感谢观众老爷的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

相关文章:

15分钟学 Go 第 42 天:RESTful API设计

第42天:RESTful API设计 目标:理解RESTful API的设计原则 在现代Web开发中,RESTful API(Representational State Transfer)已经成为了标准的架构风格,用于实现客户端与服务器之间的通信。通过遵循REST的设…...

如何安全的中断一个运行中的线程?

文心快码进入3.0时代, 最新发布的代码问答、编码、Debug、单测、安全智能体, 分别在开发的设计、编码、构建、测试验证全流程通过AI赋能,让效率更高、效果更好。可以通过自然语言对话,独立为你完成一项编码任务。 👉点…...

【121. 买卖股票的最佳时机】——贪心算法/动态规划

121. 买卖股票的最佳时机 一、题目难度 简单 三、题目描述 给定一个数组 prices,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择某一天买入这只股票,并选择在未来的某一个不同的日子卖出该股票。设计一个算法来计算你所能获…...

LLMs之Calculate:利用大语言模型技术基于文本内容实现数字计算能力的简介、常用方法、代码实现之详细攻略

LLMs之Calculate:利用大语言模型技术基于文本内容实现数字计算能力的简介、常用方法、代码实现之详细攻略 导读:在基于大语言模型(LLM)技术实现数字计算能力的背景下,文本内容的理解和计算过程涉及多个领域的交叉技术,包括自然语言处理(NLP)、机器学习、以及数值计算。…...

LeetCode题练习与总结:判断子序列--392

一、题目描述 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一…...

json数据结构的转换

# json可用于赌徒与原件数据的转换(json以字符串的形式储存数据,在通过json进行两种语言的转换时,应先将数据类型转换成列表或字典,再由列表或字典转换成json字符串,最后由json字符串转换成另一种语言的列表或字典数据…...

mysql删除语句:@Update(“TRUNCATE TABLE employee“)讲解

这个 SQL 语句: TRUNCATE TABLE employee是一个 SQL DDL(数据定义语言) 操作,用于清空数据库表中的所有记录,但不会删除表结构(即列和索引等)。 逐部分解释: TRUNCATE:…...

如何修改浏览器指纹?

网络安全日益重要,我们的上网行为变得越来越容易被追踪和分析。其中,浏览器指纹就是一种强大的技术手段,它可以说是你上网的身份象征。 一、浏览器指纹是什么 浏览器指纹是网站和在线平台用来收集关于你的浏览器、设备和网络的详细信息的一…...

实现3D热力图

实现思路 首先是需要用canvas绘制一个2D的热力图,如果你还不会,请看json绘制热力图。使用Threejs中的canvas贴图,将贴图贴在PlaneGeometry平面上。使用着色器材质,更具json中的数据让平面模型 拔地而起。使用Threejs内置的TWEEN&…...

GEE ui界面实现:用户自画多边形, 按面积比例在多边形中自动生成样点,导出多边形和样点shp,以及删除上一组多边形和样点(有视频效果展示)

零、背景 这几天在选样点,发现GEE有强大的ui功能,于是应用在我的工作上。 下述代码实现了几个功能: ①用户可以自己勾勒多边形,随后程序会按面积比例在多边形中自动生成样点,同时根据改多边形的区域生成区域平均月N…...

React diff算法和Vue diff算法的主要区别

React和Vue都是流行的前端框架,它们各自实现了diff算法来优化虚拟DOM的更新过程。以下是React diff算法和Vue diff算法的主要区别: 1. diff策略 React diff算法: React的diff算法主要采用了同层级比较的策略,即它不会跨层级比较节…...

WSL 2 中 FastReport 与 FastCube 的设置方法与优化策略

软件开发人员长期以来一直在思考这个问题:“我们如何才能直接在 Windows 中运行 Linux 应用程序,而无需使用单独的虚拟机?” WSL 技术为这个问题提供了一个可能的答案。WSL 的历史始于 2016 年。当时,其实现涉及使用 Windows 内核…...

《线性代数》学习笔记

列向量无关 上个星期继续学线性代数,一个矩阵,如何判断它是的列向量有几个是线性无关呢?其实有好几个方法。第一个就是一个一个判断。 先选定一个,然后看下这两个,怎么看呢?如果两个列向量线性相关&#…...

Redis三种集群模式:主从模式、哨兵模式和Cluster模式

目录标题 1、背景及介绍2、 Redis 主从复制2.1、主从复制特点2.2、Redis主从复制原理2.3 PSYNC 工作原理2.3.1、启动或重连判断:2.3.2、第一次同步处理:2.3.3、断线重连处理:2.3.4、主节点响应2.3.5、全量同步触发条件:2.3.6、复制…...

CDH大数据平台部署

二、CDH简介 全称Cloudera’s Distribution Including Apache Hadoop。 hadoop的版本 (Apache、CDH、Hotonworks版本) 在公司中一般使用cdh多一些(收费的)、也有公司使用阿里云大数据平台、微软的大数据平台。 国内也有一些平台:星环大数…...

7.4、实验四:RIPv2 认证和触发式更新

源文件 一、引言:为什么要认证和采用触发式更新? 1. RIP v2 认证 RIP(Routing Information Protocol)版本 2 添加了认证功能,以提高网络的安全性。认证的作用主要包括以下几点: 防止路由欺骗 RIP v1 是不…...

【一步步开发AI运动小程序】二十一、如果将AI运动项目配置持久化到后端?

**说明:**本文所涉及的AI运动识别、计时、计数能力,都是基于云智「Ai运动识别引擎」实现。云智「Ai运动识别」插件识别引擎,可以为您的小程序或Uni APP赋于原生、本地、广覆盖、高性能的人体识别、姿态识别、10余种常见的运动计时、计数识别及…...

LED和QLED的区别

文章目录 1. 基础背光技术2. 量子点技术的引入3. 色彩表现4. 亮度和对比度5. 能效6. 寿命7. 价格总结 LED和 QLED都是基于液晶显示(LCD)技术的电视类型,但它们在显示技术、色彩表现和亮度方面有一些关键区别。以下是两者的详细区别&#xff…...

2024 年Postman 如何安装汉化中文版?

2024 年 Postman 的汉化中文版安装教程...

转化古老的Eclipse项目为使用gradle构建

很多古老的Java项目,是使用Eclipse作为IDE开发的。 那么,使用其它IDE的开发者,如何快速地进入这种古老项目的开发呢?或者说,一个Eclipse构建的古老项目,能不能转化成一个IDE无关的项目,进而所有…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...