Golang 使用Gin创建Restful API

news2024/12/28 18:22:38

Golang 使用Gin创建Restful API

今天学习下Go语言如何集成Gin框架编写Restful Web API的基本操作。Gin框架简化了Go原生语言构建Web应用程序的复杂度,在今天的学习中,将学会使用Gin构建路由请求、数据检索、JSON响应封装等最简单的Web服务。

基本要求

  • Go 1.16 及更高版本
  • 合适的编译工具 - text编辑器也满足要求
  • 命令终端 - Linux、Mac系统shell, Windows系统的Cmd、PowerShell
  • curl 工具 - curl 是一个利用URL语法在命令行下工作的文件传输工具

设计API

遵循Restful API 架构风格,构建以下两个Http Api:

  • /albums
  • GET - 获取数据列表,以JSON格式返回
  • POST - 接收客户端发送的JSON请求,新增数据项
  • /albums/:id
    • GET - 根据指定ID获取特定的数据,跟SpringBoot框架动态ID使用 {id} 不同,Gin框架在语法上使用 冒号: 表明该参数为为前端传递的动态参数

代码开发

创建项目

  • 创建项目目录
$ mkdir web-service-gin
$ cd web-service-gin
  • 项目初始化 - 使用go mod init 命令初始化
$ go mod init example/web-service-gin

在这里插入图片描述

该命令会自动创建go.mod文件,该文件用于管理Go应用中的依赖,作用类似于Java语言中的Maven

创建数据格式

为了简化Demo开发难度,将直接使用内存中的数据,不跟DB进行交互(真实项目中不推荐)。首先在项目根目录下创建main.go文件,文件内容如下:

package main

// 定义JSON 返回格式
type album struct {
    ID     string  `json:"id"`
    Title  string  `json:"title"`
    Artist string  `json:"artist"`
    Price  float64 `json:"price"`
}

// 内存中存储的数组
var albums = []album{
    {ID: "1", Title: "Blue Train", Artist: "John Coltrane", Price: 56.99},
    {ID: "2", Title: "Jeru", Artist: "Gerry Mulligan", Price: 17.99},
    {ID: "3", Title: "Sarah Vaughan and Clifford Brown", Artist: "Sarah Vaughan", Price: 39.99},
}

Restful API

返回数据列表

当客户端使用Get方式请求**/albums**路径时,需要按照JSON格式返回所有数据(这里先不讨论分页)。实现该需求,代码开发时,需要注意以下两点

  1. 准备响应逻辑
  2. 将请求路径跟响应逻辑进行匹配
  • 处理函数
// 在main.go新增函数
// getAlbums responds with the list of all albums as JSON.
func getAlbums(c *gin.Context) {
    c.IndentedJSON(http.StatusOK, albums)
}

代码说明:

  • 编写getAlbums函数,该函数接受gin.Context参数。您可以为该函数指定任何你喜欢的函数名称。gin.Context是Gin框架中最重要的部分,它携带HTTP Request请求的所有细节,如请求参数、验证、JSON序列化等

  • 调用Context.IndedJSON将结构序列化为JSON并将其添加到响应中。Context.IndedJSON函数的第一个参数是要发送给客户端的HTTP状态代码。在这里默认为200,表示请求成功

  • **路由处理 **

// 在 main.go 文件中新增
func main() {
    router := gin.Default()
    router.GET("/albums", getAlbums)

    router.Run("localhost:8080")
}

代码说明

  • 使用默认方式初始化Gin Router路由
  • 使用GET方法关联**/albums** 和 getAlbums 函数
  • 调用Run函数启动服务器

新增依赖

// 在 main.go 文件中新增
package main

import (
    "net/http"
    "github.com/gin-gonic/gin"
)
  • 运行服务
  1. 添加依赖 - 使用以下命令 拉取Gin框架依赖包

    $ go get .
    

    在这里插入图片描述

  2. 运行服务

    $ go run .
    
  3. 使用curl工具发送Http请求 - 打开另外的终端发送请求

    curl http://localhost:8080/albums
    

    在这里插入图片描述

新增数据项

使用同样的方式,在服务器端编写POST请求接收客户端数据新增数据项。跟之前Get请求稍微不同的是,该请求需要从request对象中解析出Body信息

  • 处理函数
// postAlbums adds an album from JSON received in the request body.
func postAlbums(c *gin.Context) {
    var newAlbum album

    // 调用BindJSON方法将数据解析到 newAlbum变量中
    if err := c.BindJSON(&newAlbum); err != nil {
        return
    }
    // 将数据追加到内存数组中
    albums = append(albums, newAlbum)
    c.IndentedJSON(http.StatusCreated, newAlbum)
}
  • 路由处理
func main() {
    router := gin.Default()
    router.GET("/albums", getAlbums)
    router.POST("/albums", postAlbums)

    router.Run("localhost:8080")
}
  • 运行服务
$ go run .
  • 发送客户端请求
$ curl http://localhost:8080/albums \
    --include \
    --header "Content-Type: application/json" \
    --request "POST" \
    --data '{"id": "4","title": "The Modern Sound of Betty Carter","artist": "Betty Carter","price": 49.99}'

在这里插入图片描述

此时,在调用获取数据列表的接口,必须返回4个数据了

返回指定数据

当客户端以GET请求方式调用 **/albums/[id]**路径,服务端需要返回指定ID的数据详情。此时该ID是由客户端动态指定的,接下来看看如何实现

  • 处理函数
// getAlbumByID locates the album whose ID value matches the id
// parameter sent by the client, then returns that album as a response.
func getAlbumByID(c *gin.Context) {
    id := c.Param("id")

    // Loop over the list of albums, looking for
    // an album whose ID value matches the parameter.
    for _, a := range albums {
        if a.ID == id {
            c.IndentedJSON(http.StatusOK, a)
            return
        }
    }
    c.IndentedJSON(http.StatusNotFound, gin.H{"message": "album not found"})
}
  • 路由匹配
func main() {
    router := gin.Default()
    router.GET("/albums", getAlbums)
    router.GET("/albums/:id", getAlbumByID)
    router.POST("/albums", postAlbums)

    router.Run("localhost:8080")
}
  • 运行服务
$ go run .
  • 客户端请求
$ curl http://localhost:8080/albums/2

在这里插入图片描述

完整代码

package main

import (
    "net/http"
    "github.com/gin-gonic/gin"
)

// album represents data about a record album.
type album struct {
    ID     string  `json:"id"`
    Title  string  `json:"title"`
    Artist string  `json:"artist"`
    Price  float64 `json:"price"`
}

// albums slice to seed record album data.
var albums = []album{
    {ID: "1", Title: "Blue Train", Artist: "John Coltrane", Price: 56.99},
    {ID: "2", Title: "Jeru", Artist: "Gerry Mulligan", Price: 17.99},
    {ID: "3", Title: "Sarah Vaughan and Clifford Brown", Artist: "Sarah Vaughan", Price: 39.99},
}

func getAlbums(c *gin.Context) {
    c.IndentedJSON(http.StatusOK, albums)
}

// postAlbums adds an album from JSON received in the request body.
func postAlbums(c *gin.Context) {
    var newAlbum album

    // Call BindJSON to bind the received JSON to
    // newAlbum.
    if err := c.BindJSON(&newAlbum); err != nil {
        return
    }

    // Add the new album to the slice.
    albums = append(albums, newAlbum)
    c.IndentedJSON(http.StatusCreated, newAlbum)
}

// getAlbumByID locates the album whose ID value matches the id
// parameter sent by the client, then returns that album as a response.
func getAlbumByID(c *gin.Context) {
    id := c.Param("id")

    // Loop over the list of albums, looking for
    // an album whose ID value matches the parameter.
    for _, a := range albums {
        if a.ID == id {
            c.IndentedJSON(http.StatusOK, a)
            return
        }
    }
    c.IndentedJSON(http.StatusNotFound, gin.H{"message": "album not found"})
}

func main() {
    router := gin.Default()
    router.GET("/albums", getAlbums)
    router.POST("/albums", postAlbums)
    router.GET("/albums/:id", getAlbumByID) 
   router.Run("localhost:8080")
}

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

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

相关文章

将本地txt文件上传至mysql

文章目录单个文件导入1.创建数据库和数据表2.使用cmd各种情况说明如果报错方案一方案二方案三mysql重启命令重启:图形页面重启当txt文件中的数据量太多时,不再适合用sql语句插入,这里介绍讲本地txt文件导入到mysql中 单个文件导入 如图所示…

【Maven】私服

目录 1. 私服介绍 问题导入 1.1 介绍 1.2 Nexus安装与启动 1.3 私服资源操作流程分析 2. 私服仓库分类 问题导入 3. 资源上传与下载 问题导入 3.1 从私服中下载依赖 3.2 上传依赖到私服中 1. 私服介绍 问题导入 这里的私服和平时我们听的国服、体验服、欧服等等有…

《深入浅出计算机组成原理》学习笔记 Day12

数据通路(上)1. 指令周期(Instruction Cycle)2. 建立数据通路3. CPU 所需要的硬件电路4. 总结参考1. 指令周期(Instruction Cycle) 计算机每执行一条指令的过程,可以分为这几个步骤&#xff1a…

MySQL三大日志

MySQL三大日志包括:undolog,redo log,binlog,它们分别有以下作用: undolog:是Innodb存储引擎生成的日志。用于事务的回滚和MVCC,保证了事务的原子性。 redo log:是Innodb存储引擎生…

【汇编】深入浅出地讲解使用六条汇编指令解决大部分汇编代码

开发环境说明 本文采用的IDE为keil5,核心板为STM32F103ZE。 在keil中添加以下两条语句即可生成汇编代码: 在上图界面中添加下述两句代码即可生成汇编代码:fromelf --bin --outputtest.bin Objects\test.axffromelf --text -a -c --outputtest…

使用Facebook分析跟踪SEO进展

Facebook是一个强大的社交平台,在这里你可以获取关于你的业务或客户的各种信息。它为你提供了一个巨大的渠道来展示你在过去一年中对行业或公司做出的贡献,以及你如何改进和优化我们所做的事情。如果不知道如何利用 Facebook来获得更多关于 SEO工作的信息…

高级数据结构:线段树入门(c++实现 + 详解)

文章目录线段树概念区间最值问题辅助函数创建线段树查询更新懒惰修改(查询)问题tag标记设计改进的更新函数关于本节的全部源代码线段树概念 线段树是一种高级数据结构,与树状数组一样,被用来处理区间查询,修改问题&am…

DDOS渗透与攻防(一)之拒绝服务攻击概念介绍

DDOS渗透与攻防 前言 DOS(Denial of Service,拒绝服务攻击),它的原理很简单,就是用我们手里的机器去给服务器发请求,如果我们手头的服务器各方面性能都比服务器的主机的性能好,那么当我们发送大量请求给服务器&#…

Day871.行锁 -MySQL实战

行锁 Hi,我是阿昌,今天学习记录的是关于行锁的内容。 MySQL 的 行锁 是在引擎层由各个引擎自己实现的。 但并不是所有的引擎都支持行锁,比如 MyISAM 引擎就不支持行锁。 不支持行锁意味着并发控制只能使用表锁,对于这种引擎的…

普通话学习

一、认识韵母是有四个声调的发错的字和音总结R:日、热、肉L:漏、乐参考:https://zhuanlan.zhihu.com/p/34571271身体(shen-1)森(sen-1) 生日(sheng-1)琴(qin-…

k8s对接smb/cifs存储

之前文章提到,k8s官方是支持nfs存储的,那么在windows常见的文件共享协议是否也支持呢。答案是肯定的。不过支持的方式是通过CSI接口进行支持的。官方提供的项目是csi-driver-smb官网:https://github.com/kubernetes-csi/csi-driver-smb安装cu…

《MFC编程》:MFC程序的分类

《MFC编程》:MFC程序的分类《MFC编程》:MFC程序的分类MFC的控制台程序MFC的库程序使用MFC库制作自己的静态库程序使用MFC库制作自己的动态库程序使用MFC库制作自己的拓展库程序MFC的窗口程序单文档视图架构程序多文档视图架构程序对话框架构程序《MFC编程…

Windows server——部署DNS服务(2)

作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​​ 目录 前言 一.配置DNS服务 1.安装步骤教程 (1)安装必要条件 &a…

【链表】链表内指定区间反转

BM2链表内指定区间反转 描述 将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)。 例如: 给出的链表为1→2→3→4→5→NULL, m2,n4m2,n4, 返回1→4→3→2→5→NULL. 数据范围&#xf…

初识 Canvas(使用 Canvas 绘制直线图形)

初识 Canvas(使用 Canvas 绘制直线图形)参考描述CanvasCanvas 与 SVGCanvas 元素替补元素使用检测绘制直线图形直线同时绘制多条直线指定起点首尾相接多彩的直线矩形描边矩形填充矩形结合体清除矩形区域多边形参考 描述 Canvas 你可以使用 JavaScript…

3 梯度下降算法

文章目录问题方法穷举法分治法梯度下降算法梯度梯度下降算法课程代码随机梯度下降算法批量梯度下降(mini-batch)课程来源: 链接其他觉得别人总结的比自己好,采用之的: 链接以及 BirandaのBlog!问题方法 穷…

飞速的网格【Steema】:TeeGrid for .NET 2023.1.23 Crack

TeeGrid for .NET 的数据网格控件为您的 Visual Studio 项目提供了一个非常快速的网格。 快速浏览 功能齐全的数据网格控件 适用于 WinForms、ASP.NET Core MVC 的易于使用的数据网格 TeeGrid for .NET 是一个原生的 c# 网格控件,目前可用于 WinForms 项目和 NET …

优先级队列(堆)

1.优先级队列1.1概念前面介绍过队列,队列是一种先进先出(FIFO)的数据结构,但是有些情况下,操作的数据可能带有优先级时,可能需要优先级高的元素先入队列,该场景中,使用队列显然不合适…

7、数据类型转换

目录 一、隐式类型转换 二、显示类型转换 类型转换是将一个值从一种类型更改为另一种类型的过程。例如,可以将String类型的数据“457”转换为数值型,也可以将任意类型的数据转换为String类型。 一、隐式类型转换 从低级类型向高级类型的转换&#xf…

一起自学SLAM算法:10.1 RTABMAP算法

连载文章,长期更新,欢迎关注: 同前面介绍过的大多数算法一样,RTABMAP也采用基于优化的方法来求解SLAM问题,系统框架同样遵循前端里程计、后端优化和闭环检测的三段式范式。这里重点讨论RTABMAP两大亮点,一个…