Go RESTful API 接口开发

文章目录

  • 什么是 RESTful API
  • Go 流行 Web 框架-Gin
  • Go HelloWorld
  • Gin 路由和控制器
  • Gin 处理请求参数
  • 生成 HTTP 请求响应
  • Gin 的学习内容
  • 实战用 Gin 框架开发 RESTful API
  • OAuth 2.0接口了解
  • 用 Go 开发 OAuth2.0 接口示例

编程有一个准则——Don‘t Repeat Yourself(不要重复你的代码)。这个准则的核心概念是:如果有一些出现重复的代码,则应该把这些代码提取出来封装成一个方法。
随着时间的积累,有了一批方法,可以把它们整合成工具类。如果工具类形成了规模,则可以把它们整合成类库。类库更系统,功能更全。不仅不要自己重复造项目中已有的“轮子”,也不要造别人已经造好的“轮子”,直接使用已有的“轮子”即可。

什么是 RESTful API

  • 资源概述
    • 资源可以是单例或集合
    • 资源也可以包含子集合资源
    • REST API 使用统一资源标识符(URI)来定位资源
  • 使用名词表示资源
    • 文档
    • 集合
    • 存储
    • 控制器
  • 保持一致性
    • 使用正斜杠( \ )表示层次关系
    • 不要在 URI 尾部使用正斜杠
    • 使用连字符( - )来提高 URI 的可读性
    • 不要使用下划线( _ )
    • 在 URI 中使用小写字母
    • 不要使用文件拓展名
  • 切勿在 URI 中使用 CRUD 函数的名称
  • 使用查询参数过滤 URI 集合

Go 流行 Web 框架-Gin

Go HelloWorld

package mainimport ("github.com/gin-gonic/gin"
)func main() {// 创建一个默认的路由引擎r := gin.Default()// GET:请求方式;/hello:请求的路径// 当客户端以GET方法请求/hello路径时,会执行后面的匿名函数r.GET("/hello", func(c *gin.Context) {// c.JSON:返回JSON格式的数据c.JSON(200, gin.H{"message": "Hello world!",})})// 启动HTTP服务,默认在0.0.0.0:8080启动服务r.Run()
}

Gin 路由和控制器

  • 路由规则
    • HTTP 请求方法
      • GET
      • POST
      • PUT
      • DELETE
    • URL 路径
      • 静态 URL 路径
      • 带路径的 URL 参数
      • 带星号(*)模糊匹配参数的 URL 路径
    • 处理器函数
  • 分组路由

Gin 处理请求参数

  • 获取 GET 请求参数
  • 获取 POST 请求参数
  • 获取 URL 路径参数
  • 将请求参数绑定到结构体

生成 HTTP 请求响应

  • 以字符串方式生成 HTTP 请求响应
  • 以 JSON 格式生成 HTTP 请求响应
  • 以 XML 格式生成 HTTP 请求响应
  • 以文件格式生成 HTTP 请求响应
  • 设置 HTTP 响应头

Gin 的学习内容

  • Gin 渲染 HTML 模板
  • Gin 处理静态资源
  • Gin 处理 cookie
  • Gin 文件上传
  • Gin 中间件
  • Gin Session

实战用 Gin 框架开发 RESTful API

mysql> CREATE TABLE `users` (->     `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,->     `phone` VARCHAR(255) DEFAULT NULL,->     `name` VARCHAR(255) DEFAULT NULL,->     `password` VARCHAR(255) DEFAULT NULL,->     PRIMARY KEY (`id`)-> ) ENGINE=InnoDB AUTO_INCREMENT=39 DEFAULT CHARSET=utf8;
package mainimport ("crypto/sha256""fmt""github.com/gin-gonic/gin""gorm.io/driver/mysql""gorm.io/gorm""net/http"
)type (User struct {ID       uint   `json:"id" gorm:"column:id"`Phone    string `json:"phone" gorm:"column:phone"`Name     string `json:"name" gorm:"column:name"`Password string `json:"password" gorm:"column:password"`}UserRes struct {ID    uint   `json:"id"`Phone string `json:"phone"`Name  string `json:"name"`}
)var db *gorm.DBfunc main() {// Connect to the databasevar err errordsn := "root:mm..1213@tcp(127.0.0.1:3306)/UserManager?charset=utf8mb4&parseTime=True&loc=Local"db, err = gorm.Open(mysql.New(mysql.Config{DriverName: "mysql",DSN:        dsn,}), &gorm.Config{})if err != nil {panic("Failed to connect to database")}// Auto migrate the User struct to create the corresponding table in the databaseerr = db.AutoMigrate(&User{})if err != nil {panic("Failed to migrate the database")}router := gin.Default()v2 := router.Group("/api/v2/user"){v2.POST("/", createUser)v2.GET("/", fetchAllUser)v2.GET("/:id", fetchUser)v2.PUT("/:id", updateUser)v2.DELETE("/:id", deleteUser)}router.Run(":8080")
}func createUser(c *gin.Context) {phone := c.PostForm("phone")name := c.PostForm("name")user := User{Phone:    phone,Name:     name,Password: md5Password(phone),}tx := db.Begin()if err := tx.Create(&user).Error; err != nil {tx.Rollback()c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error(),})return}tx.Commit()c.JSON(http.StatusCreated, gin.H{"status":  http.StatusCreated,"message": "User created successfully!","ID":      user.ID,})
}func md5Password(password string) string {hash := sha256.Sum256([]byte(password))return fmt.Sprintf("%x", hash)
}func fetchAllUser(c *gin.Context) {var user []Uservar _userRes []UserResdb.Find(&user)if len(user) <= 0 {c.JSON(http.StatusNotFound,gin.H{"status":  http.StatusNotFound,"message": "No user found!",})return}for _, item := range user {_userRes = append(_userRes,UserRes{ID:    item.ID,Phone: item.Phone,Name:  item.Name,})}c.JSON(http.StatusOK,gin.H{"status": http.StatusOK,"data":   _userRes,})
}func fetchUser(c *gin.Context) {var user UserID := c.Param("id")db.First(&user, ID)if user.ID == 0 {c.JSON(http.StatusNotFound, gin.H{"status": http.StatusNotFound, "message": "No user found!"})return}res := UserRes{ID:    user.ID,Phone: user.Phone,Name:  user.Name,}c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": res})
}func updateUser(c *gin.Context) {var user UseruserID := c.Param("id")db.First(&user, userID)if user.ID == 0 {c.JSON(http.StatusNotFound, gin.H{"status": http.StatusNotFound, "message": "No user found!"})return}db.Model(&user).Update("phone", c.PostForm("phone"))db.Model(&user).Update("name", c.PostForm("name"))c.JSON(http.StatusOK, gin.H{"status":  http.StatusOK,"message": "Updated User Successfully!",})
}func deleteUser(c *gin.Context) {var user UseruserID := c.Param("id")db.First(&user, userID)if user.ID == 0 {c.JSON(http.StatusNotFound, gin.H{"status":  http.StatusNotFound,"message": "No user found!",})return}db.Delete(&user)c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "User deleted successfully!"})
}
  • GoLand Tools-Http Client 测试
DELETE http://127.0.0.1:8080/api/v2/user/58
Content-Type: application/x-www-form-urlencodedphone=10086&name=chYiDong

OAuth 2.0接口了解

用 Go 开发 OAuth2.0 接口示例

  • 做了解之后用到可能性比较小
  1. GitHub OAuth 应用注册
  • 注册页面:https://github.com/settings/applications/new
    在这里插入图片描述
  1. 登录授权页面
<!DOCTYPE HTML>
<html>
<body>
<a href="https://github.com/login/oauth/authorize?client_id=5bcf804cfeb0ef7120f5&redirect_uri=http://localhost:8087/oauth/redirect">Login by GitHub
</a>
</body>
</html>
  1. 欢迎界面
<!DOCTYPE HTML>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, INItial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Hello</title>
</head>
<body>
</body>
<script>//获取url参数function getQueryVariable(variable) {var query = window.location.search.substring(1);var vars = query.split("&");for (var i = 0; i < vars.length; i++) {var pair = vars[i].split("=");if (pair[0] == variable) {return pair[1];}}return (false);}// 获取access_tokenconst token = getQueryVariable("access_token");// 调用用户信息接口fetch('https://api.github.com/user', {headers: {Authorization: 'token ' + token}})// 解析请求的JSON.then(res => res.json()).then(res => {// 返回用户信息const nameNode = document.createTextNode(`Hi, ${res.name}, Welcome to login our site by GitHub!`)document.body.appendChild(nameNode)})
</script>
</html>
  1. Go 语言编写
package mainimport ("encoding/json""fmt""html/template""net/http""os"
)// const clientID = "<your client id>"
const clientID = "5bcf804cfeb0ef7120f5"// const clientSecret = "<your client secret>"
const clientSecret = "8d31102da18096d13eb6ec819cd81ca898ed7189"func hello(w http.ResponseWriter, r *http.Request) {if r.Method == "GET" {t, _ := template.ParseFiles("hello.html")t.Execute(w, nil)}
}func login(w http.ResponseWriter, r *http.Request) {if r.Method == "GET" {t, _ := template.ParseFiles("login.html")t.Execute(w, nil)}
}func main() {http.HandleFunc("/login", login)http.HandleFunc("/", hello)http.HandleFunc("/hello", hello)httpClient := http.Client{}http.HandleFunc("/oauth/redirect", func(w http.ResponseWriter, r *http.Request) {err := r.ParseForm()if err != nil {fmt.Fprintf(os.Stdout, "could not parse query: %v", err)w.WriteHeader(http.StatusBadRequest)}code := r.FormValue("code")reqURL := fmt.Sprintf("https://github.com/login/oauth/access_token?"+"client_id=%s&client_secret=%s&code=%s", clientID, clientSecret, code)req, err := http.NewRequest(http.MethodPost, reqURL, nil)if err != nil {fmt.Fprintf(os.Stdout, "could not create HTTP request: %v", err)w.WriteHeader(http.StatusBadRequest)}req.Header.Set("accept", "application/json")res, err := httpClient.Do(req)if err != nil {fmt.Fprintf(os.Stdout, "could not send HTTP request: %v", err)w.WriteHeader(http.StatusInternalServerError)}defer res.Body.Close()var t AccessTokenResponseif err := json.NewDecoder(res.Body).Decode(&t); err != nil {fmt.Fprintf(os.Stdout, "could not parse JSON response: %v", err)w.WriteHeader(http.StatusBadRequest)}w.Header().Set("Location", "/hello.html?access_token="+t.AccessToken)w.WriteHeader(http.StatusFound)})http.ListenAndServe(":8087", nil)
}type AccessTokenResponse struct {AccessToken string `json:"access_token"`
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/121105.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在Windows和Linux系统上监听文件夹的变动?

文章目录 如何在Windows和Linux系统上监听文件夹的变动&#xff1f;读写文件文件系统的操作缓冲和流文件改变事件 如何在Windows和Linux系统上监听文件夹的变动&#xff1f; libuv库实现了监听整个文件夹的修改。本文详细介绍libuv库文件读写和监听的的实现方法。libuv库开发了…

Unity的碰撞检测(六)

温馨提示&#xff1a;本文基于前一篇“Unity的碰撞检测(五)”继续探讨两个游戏对象具备刚体的BodyType均为Dynamic&#xff0c;但是Collision Detection属性不同的碰撞检测&#xff0c;阅读本文则默认已阅读前文。 &#xff08;一&#xff09;测试说明 在基于两个游戏对象都具…

ClickHouse UDF 官方示例Example报错解决方案

目录 一、环境版本二、官方示例三、解决方案1.Python脚本运行缺少权限2. 缺少Python3运行环境 四、参考借鉴 一、环境版本 环境版本docker clickhouse22.3.10.22 docker pull clickhouse/clickhouse-server:22.3.10.22二、官方示例 官网文档 test_function使用 XML 配置创建…

element plus的icon使用及动态调用

在element plus中 icon图标不再能够通过类名直接使用&#xff1a; //element ui <i class"el-icon-plus"></i> element plus 的图标资源引入请直接访问官网 <el-icon><Present /></el-icon> 动态调用icon图表需要依靠vue的内置组…

使用 PointNet 进行3D点集(即点云)的分类

点云分类 介绍 无序3D点集(即点云)的分类、检测和分割是计算机视觉中的核心问题。此示例实现了开创性的点云深度学习论文PointNet(Qi 等人,2017)。 设置 如果使用 colab 首先安装 trimesh !pip install trimesh。 import os import glob import trimesh import numpy as…

TSINGSEE青犀省级高速公路视频上云联网方案:全面实现联网化、共享化、智能化

一、需求背景 随着高速铁路的建设及铁路管理的精细化&#xff0c;原有的模拟安防视频监控系统已经不能满足视频监控需求&#xff0c;越来越多站点在建设时已开始规划高清安防视频监控系统。高速公路视频监控资源非常丰富&#xff0c;需要对其进行综合管理与利用。通过构建监控…

MySQL比较两个表数据的差异

一、几种比较方式 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;连接两个表的相同记录&#xff0c;通过比较连接后的结果集&#xff0c;找出相同和不同的数据。外连接&#xff08;LEFT JOIN或RIGHT JOIN&#xff09;&#xff1a;连接两个表的所有记录&#xff0c;包括…

荣电集团与钕希科技签署全面战略合作

10月26日&#xff0c;荣电集团&#xff08;以下简称荣电&#xff09;与钕希科技南京有限公司&#xff08;以下简称钕希科技&#xff09;今天在合肥市签署全面战略合作协议&#xff0c;联合进军混合现实&#xff08;Mixed Reality&#xff0c;以下简称MR&#xff09;空间计算高科…

【MySQL】常见错误汇总

目录 一、远程连接MySQL用户权限问题 解决方案 二、mysql使用聚合函数group by 报错 解决方案一 解决方案二 三、MySQL导入数据时 server has gone away 解决方案一 解决方案二 一、远程连接MySQL用户权限问题 远程连接MySQL时&#xff0c;提示&#xff1a;ERROR 1130:…

Java练习题2021-4

"某游戏公司设计了一个奖励活动&#xff0c;给N个用户(1≤N≤10^7)连续编号为1到N&#xff0c;依据用户的编号S发放奖励。 发放奖励规则为&#xff1a; 公司随机设定三个非零正整数x&#xff0c;y&#xff0c;z。 如果S同时是x、y的倍数&#xff0c;奖励2张卡片&#xff1…

如何绘制【逻辑回归】中threshold参数的学习曲线

threshold参数的意义是通过筛选掉低于threshold的参数&#xff0c;来对逻辑回归的特征进行降维。 首先导入相应的模块&#xff1a; from sklearn.linear_model import LogisticRegression as LR from sklearn.datasets import load_breast_cancer from sklearn.model_selecti…

linux 更换java 版本

查看可安装版本 yum -y list java* 安装(会直接替换jdk版本) yum install -y java-1.8.0-openjdk-devel.x86_641 查看java 版本 ls /usr/lib/jvm/ 2 设置java版本&#xff08;根据提示的编号&#xff09; sudo update-alternatives --config java 3 设置环境变量 sudo nan…

内核进程的调度与进程切换

进程被创建到了链表中&#xff0c;如何再进行进一步的调用和调用&#xff1f; 进程调度 void schedule(void)&#xff1b; 进程调度 switch_to(next); 进程切换函数 void schedule(void) {int i,next,c;struct task_struct ** p;/* check alarm, wake up any i…

nginx配置反向代理和动静分离应用

一. Nginx配置反向代理和实现动静分离与虚拟主机流程图&#xff1a; 二 .Nginx配置反向代理和实现动静分离与虚拟主机实现详细配置和效果图 2.1 nginx 配置反向代理 #在nginx.conf配置server同级下配置 include tomcat.conf# vim tomcat.conf upstream api.z.mukewang.com{…

pdf相关的python库

本文说明 最近接触pdf信息抽取&#xff0c;使用了几个操作pdf的python库&#xff0c;这里简单纪录下。 pypdf pypdf是一个免费的、开源的纯python PDF库&#xff0c;能够拆分、合并、裁剪和转换PDF文件的页面。它还可以为PDF文件添加自定义数据、查看选项和密码。pypdf也可以…

mac 查看GPU使用

首先搜索活动监视器 然后 点击窗口->gpu历史记录 记住不是立马出结果&#xff0c;而是 需要等半分钟左右的

埋点日志解决方案——Golang+Gin+Sarama VS Java+SpringCloudGateway+ReactorKafka

埋点日志解决方案——GolangGinSarama VS JavaSpringCloudGatewayReactorKafka 之前我就写过几篇OpenRestylua-kafka-client将埋点数据写入Kafka的文章&#xff0c;如下&#xff1a; Lua将Nginx请求数据写入Kafka——埋点日志解决方案 python定时任务执行shell脚本切割Nginx…

PS笔记2_钢笔工具的形状和路径

本文目录 前言Step 1 形状的用法&#xff1a;画图Step 2 路径的用法&#xff1a;抠图 前言 当我们在PS中选择钢笔工具时&#xff0c;上方功能栏中可以选择钢笔的功能项&#xff0c;有三种选项&#xff1a;形状&#xff0c;路径和像素。最常用的就是“形状”和“路径”。本博文…

华为实验基础(1):交换机基础

一、交换机的分类 1、 根据交换方式划分&#xff1a; 存储转发式交换 (Store and Forward) 直通式交换 (Cut-through) 碎片过滤式交换 (Fragment Free) 2、 根据交换的协议层划分&#xff1a; 第二层交换&#xff1a;根据 MAC 地址进行交换 第三层交换&…

Hadoop3.0大数据处理学习4(案例:数据清洗、数据指标统计、任务脚本封装、Sqoop导出Mysql)

案例需求分析 直播公司每日都会产生海量的直播数据&#xff0c;为了更好地服务主播与用户&#xff0c;提高直播质量与用户粘性&#xff0c;往往会对大量的数据进行分析与统计&#xff0c;从中挖掘商业价值&#xff0c;我们将通过一个实战案例&#xff0c;来使用Hadoop技术来实…