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.rhkb.cn/news/171530.html

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

相关文章

vue源码分析(三)——new Vue 的过程(详解data定义值后如何获取的过程)

文章目录 零、准备工作1.创建vue2项目2.修改main.js 一、import Vue from vue引入的vue是哪里来的&#xff08;看导入node_modules包&#xff09;1&#xff1a; 通过node_modules包的package.json文件2&#xff1a; 通过配置中的main入口文件进入开发环境的源码&#xff08;1&a…

java将list转为逗号隔开字符串,将逗号连接的字符串转成字符数组,​将逗号分隔的字符串转换为List​(Java逗号分隔-字符串与数组相互转换)

一、通过testList.stream().collect(Collectors.joining(",")) &#xff0c;通过流转换&#xff0c;将list转为逗号隔开字符串 List<String> testList new ArrayList<>(); testList.add("test1"); testList.add("test2"); testList…

如何查找特定基因集合免疫基因集 炎症基因集

温故而知新&#xff0c;再次看下Msigdb数据库。它更新了很多内容。给我们提供了一个查询基因集的地方。 关注微信&#xff1a;生信小博士 比如纤维化基因集&#xff1a; 打开网址&#xff1a;https://www.gsea-msigdb.org/gsea/msigdb/index.jsp 2.点击search 3.比如我对纤维…

基于Python Django 的微博舆论、微博情感分析可视化系统(V2.0)

文章目录 1 简介2 意义3 技术栈Django 4 效果图微博首页情感分析关键词分析热门评论舆情预测 5 推荐阅读 1 简介 基于Python的微博舆论分析&#xff0c;微博情感分析可视化系统&#xff0c;项目后端分爬虫模块、数据分析模块、数据存储模块、业务逻辑模块组成。 Python基于微博…

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

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

浏览器事件循环 (event loop)

进程与线程 进程 进程的概念 进程是操作系统中的一个程序或者一个程序的一次执行过程&#xff0c;是一个动态的概念&#xff0c;是程序在执行过程中分配和管理资源的基本单位&#xff0c;是操作系统结构的基础。 简单的来说&#xff0c;就是一个程序运行开辟的一块内存空间&a…

【计算机网络笔记】Cookie技术

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

Fourier分析导论——第1章——Fourier分析的起源(E.M. Stein R. Shakarchi)

第 1 章 Fourier分析的起源 (The Genesis of Fourier Analysis) Regarding the researches of dAlembert and Euler could one not add that if they knew this expansion, they made but a very imperfect use of it. They were both persuaded that an arbitrary and d…

如何使用手机蓝牙设备作为电脑的解锁工具像动态锁那样,蓝牙接近了电脑,电脑自动解锁无需输入开机密码

环境&#xff1a; Win10 专业版 远程解锁 蓝牙解锁小程序 问题描述&#xff1a; 如何使用手机蓝牙设备作为电脑的解锁工具像动态锁那样&#xff0c;蓝牙接近了电脑&#xff0c;电脑自动解锁无需输入开机密码 手机不需要拿出来&#xff0c;在口袋里就可以自动解锁&#xff…

calcite 校验层总结

1、校验的作用 1&#xff09;完善语义信息 例如在SQL语句中&#xff0c;如果碰到select * 这样的指令&#xff0c;在SQL的语义当中&#xff0c;“*” 指的是取出对应数据源中所有字段的信息&#xff0c;因此就需要根据元数据信息来展开。 2&#xff09;结合元数据信息来纠偏…

Java游戏修炼手册:2023 最新学习线路图

前言 有没有一种令人兴奋的学习方法&#xff1f;当然有&#xff01;绝对有&#xff01;而且我要告诉你&#xff0c;学习的快乐可以媲美游戏的刺激。 小学时代&#xff0c;我曾深陷于一款名为"八百万勇士的梦"的游戏。每当放学&#xff0c;我总是迫不及待地打开电脑&a…

JSON(详解)

目录 什么是JSON&#xff1f; 哪里会用到JSON&#xff1f; JSON的特点 JSON的优点 JSON的缺点 JSON和cJSON的关系 什么是JSON&#xff1f; JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式。它以易于阅读和编写的文本格式来存储和表示…

Kafka - 3.x 图解Broker总体工作流程

文章目录 Zk中存储的kafka的信息Kafka Broker总体工作流程1. broker启动后向zk中注册2. Controller谁先启动注册&#xff0c;谁说了算3. 由选举出来的Controller监听brokers节点的变化4. Controller决定leader选举5. Controller将节点信息上传到Zk中6. 其他Controller从zk中同步…

为什么说大模型微调是每个人都必备的核心技能?

▼最近直播超级多&#xff0c;预约保你有收获 近期直播&#xff1a;《基于开源 LLM 大模型的微调&#xff08;Fine tuning&#xff09;实战》 0 — 为什么要对 LLM 大模型进行微调&#xff08;Fine tuning&#xff09;&#xff1f; LLM 大模型&#xff08;比如&#xff1a;Chat…

安全狗安装

安装waf 关闭apache程序及httpd.exe进程; 运行cmd&#xff0c;cd进入apache/bin文件夹目录&#xff0c; 执行httpd.exe -k install -n apache2.4.39; 启动apache,启动phpstudy 安全狗安装服务名称填写apache2.4.39; 安装安全狗之后就会提示报错 网站防护 可以设备黑白名单 漏…

JAVA实现校园二手交易系统 开源

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 二手商品档案管理模块2.3 商品预约管理模块2.4 商品预定管理模块2.5 商品留言板管理模块2.6 商品资讯管理模块 三、实体类设计3.1 用户表3.2 二手商品表3.3 商品预约表3.4 商品预定表3.5 留言表3.6 资讯…

Leo赠书活动-03期 【ChatGPT 驱动软件开发:AI 在软件研发全流程中的革新与实践 】

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…

网络协议--TFTP:简单文件传送协议

15.1 引言 TFTP(Trivial File Transfer Protocol)即简单文件传送协议&#xff0c;最初打算用于引导无盘系统&#xff08;通常是工作站或X终端&#xff09;。和将在第27章介绍的使用TCP的文件传送协议&#xff08;FTP&#xff09;不同&#xff0c;为了保持简单和短小&#xff0…

【微信小程序】数字化会议OA系统之投票模块(附源码)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《微信小程序开发实战》。&#x1f3af;&#x1f3a…

了解单域名证书和通配符证书的区别,选择合适的SSL证书解决方案

随着互联网的不断发展&#xff0c;网站安全性问题一直备受关注&#xff0c;在保护网站数据安全的过程中&#xff0c;SSL证书一直发挥着至关重要的作用。而在选择SSL证书时&#xff0c;单域名证书和通配符证书是两种常见的选择。本文将详细介绍单域名证书和通配符证书的区别&…