Go开发指南-Gin与Web开发

目录:
(1)Go开发指南-Hello World
(2)Go开发指南-Gin与Web开发
(3)Go开发指南-Goroutine

Gin 是一个用 Go 语言编写的轻量级、高性能的 Web 框架,主要用于构建 API 服务和微服务。由于其简洁的 API 设计和强大的路由功能,Gin 在 Go 社区中广受欢迎。

运行Web程序

创建一个目录web-service-gin,初始化模块

go mod init example/web-service-gin

创建main.go

package mainimport ("net/http""github.com/gin-gonic/gin"
)type album struct {ID     string  `json:"id"`Title  string  `json:"title"`Artist string  `json:"artist"`Price  float64 `json:"price"`
}func main() {router := gin.Default()router.GET("/albums", getAlbums)router.Run("localhost:8080")
}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)
}

将其运行起来: go run .,就能访问http://lcoalhost:8080/albums了。

再新增一个POST接口:


// add post handler
func postAlbums(c *gin.Context) {var newAlbum albumif err := c.BindJSON(&newAlbum); err != nil {return}albums = append(albums, newAlbum)c.IndentedJSON(http.StatusCreated, newAlbum)
}// update router
router.POST("/albums", postAlbums)

此时用POST方法来访问就可以来新增album了。

根据指定id返回

新增一个接口:

// add getById handler
func getAlbumByID(c *gin.Context) {id := c.Param("id")for _, a := range albums {if a.ID == id {c.IndentedJSON(http.StatusOK, a)return}}c.IndentedJSON(http.StatusNotFound, gin.H{"message": "album not found"})
}// update router
router.GET("/albums/:id", getAlbumByID)

发起请求:curl http://localhost:8080/albums/1 即可获取第一个album了。

连接数据库

Web服务中访问数据库是必不可少的,下面以postgresql数据库为例来演示如何连接数据库。

先创建数据库和表:

CREATE DATABASE music;CREATE TABLE album(id SERIAL PRIMARY KEY,title VARCHAR(36) NOT NULL,artist VARCHAR(36) NOT NULL,price NUMBRIC(10, 2) NOT NULL
) ;INSERT INTO album(title, artist, price) VALUES
('Album A', 'Artist 1', 9.99),
('Album B', 'Artist 1', 14.99),
('Album C', 'Artist 2', 19.99);

创建main.go:

package mainimport ("database/sql""fmt""log""net/http""github.com/gin-gonic/gin"_ "github.com/lib/pq"
)type Album struct {ID     string  `json:"id"`Title  string  `json:"title"`Artist string  `json:"artist"`Price  float64 `json:"price"`
}var db *sql.DBfunc main() {dsn := "user=postgres password=admin dbname=music sslmode=disable"var err errordb, err = sql.Open("postgres", dsn)if err != nil {log.Fatal("Failed to connect to database", err)}pingErr := db.Ping()if pingErr != nil {log.Fatal("Failed to ping database", pingErr)}fmt.Println("Connected!")router := gin.Default()router.GET("/albums/:artist", getAlbumsByArtist)router.Run("localhost:8080")
}func getAlbumsByArtist(c *gin.Context) {artist := c.Param("artist")albums, err := queryAlbumsByArtist(artist)if err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})return}if len(albums) == 0 {c.JSON(http.StatusNotFound, gin.H{"message": "No albums found for artist"})return}c.JSON(http.StatusOK, albums)
}func queryAlbumsByArtist(artist string) ([]Album, error) {rows, err := db.Query("SELECT * FROM album WHERE artist = $1", artist)if err != nil {return nil, err}defer rows.Close()var albums []Albumfor rows.Next() {var album Albumif err := rows.Scan(&album.ID, &album.Title, &album.Artist, &album.Price); err != nil {return nil, err}albums = append(albums, album)}if err = rows.Err(); err != nil {return nil, err}return albums, nil
}

注意,在导入包时使用了 _ "github.com/lib/pq", 此处_表示该包被导入,但不直接在代码中使用,其作用是执行该包的初始化函数。这种用法称为空白标识符导入,通常用于以下几种情况:

  • 注册驱动程序或插件
  • 执行包的初始化代码

访问curl http://localhost:8080/albums/Artist%201,即可获取返回结果。

Gin的中间件

Gin的中间件函数可以在请求到达handler之前做一些前置处理或者在响应返回给客户端之前做后置处理。Gin提供了很多内置的中间件函数,比如常见的日志记录,CORS处理等。开发者也可以根据需要自己定制中间件函数。

日志中间件

下面以日志中间件函数为例来说明如何做日志前处理:

package mainimport ("log""time""github.com/gin-gonic/gin"
)func LoggerMiddleware() gin.HandlerFunc {return func(c *gin.Context) {start := time.Now()c.Next()duration := time.Since(start)log.Printf("Request - Method: %s | Status : %d | Duration: %v", c.Request.Method, c.Writer.Status(), duration)}
}func main() {router := gin.Default()router.Use(LoggerMiddleware())router.GET("/", func(c *gin.Context) {c.String(200, "Hello, World!")})router.Run(":8080")
}

访问 http://localhost:8080/, 会看到输出日志中打印日志:

Request - Method: GET | Status : 200 | Duration: 24.291µs

鉴权中间件

假设我们需要在请求被处理之前对其进行鉴权,可以定义鉴权中间件:

package mainimport ("github.com/gin-gonic/gin"
)func AuthMiddleware() gin.HandlerFunc {return func(c *gin.Context) {apiKey := c.GetHeader("X-API-Key")if apiKey == "" {c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})return}c.Next()}
}func main() {router := gin.Default()authGroup := router.Group("/api")authGroup.Use(AuthMiddleware()){authGroup.GET("/data", func(c *gin.Context) {c.JSON(200, gin.H{"message": "Authenticated and authorized!"})})}router.Run(":8080")
}

当访问http://localhost:8080/api/data时,返回{"error":"Unauthorized"}错误。

注意,中间件可以是全局生效的,也可以是局部生效的,取决于其使用的位置。例如authGroup.Use(AuthMiddleware()) 表明此中间件只在authGroup这个路由中生效。

路由分组

上文中设置鉴权中间件时对路由进行了分组。Gin允许对路由进行分组,以便更好地组织和维护代码。

下面继续展示路由分组功能:

package mainimport ("github.com/gin-gonic/gin"
)func AuthMiddleware() gin.HandlerFunc {return func(c *gin.Context) {apiKey := c.GetHeader("X-API-Key")if apiKey == "" {c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})return}c.Next()}
}func main() {router := gin.Default()public := router.Group("/public"){public.GET("/info", func(c *gin.Context) {c.String(200, "Public information")})public.GET("/products", func(c *gin.Context) {c.String(200, "Public product list")})}private := router.Group("/private")private.Use(AuthMiddleware()){private.GET("/data", func(c *gin.Context) {c.String(200, "Private data accessible after authentication")})private.POST("/create", func(c *gin.Context) {c.String(200, "Create a new resource")})}router.Run(":8080")
}

控制器与Handlers

当后端接口不断增加时,如果将所有的业务逻辑全部放在路由的handlers里面是不明智的。

最好是增加控制器来处理业务逻辑,如下所示:

package mainimport ("github.com/gin-gonic/gin"
)type UserController struct{}func (uc *UserController) GetUserInfo(c *gin.Context) {userID := c.Param("id")c.JSON(200, gin.H{"id": userID, "name": "John Doe", "email": "john@example.com"})
}func main() {router := gin.Default()userController := &UserController{}router.GET("/users/:id", userController.GetUserInfo)router.Run(":8080")
}

参考资料

[1]. https://go.dev/doc/tutorial/web-service-gin

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

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

相关文章

vue3+vite 前端打包不缓存配置

最近遇到前端部署后浏览器得清缓存才能出现最新页面效果得问题 所以…按以下方式配置完打包就没啥问题了,原理很简单就是加个时间戳 /* eslint-disable no-undef */ import {defineConfig, loadEnv} from vite import path from path import createVitePlugins from…

基于Qt/C++全局键盘和鼠标事件监控工具

项目介绍: 该项目实现了一个基于 Qt 框架的全局键盘和鼠标事件监控工具,主要功能包括: 实时监控全局键盘事件:捕获并显示所有键盘按键,并将按键的虚拟键码转为键名显示。实时监控全局鼠标事件:捕获并显示…

华为数通HCIA系列第5次考试-【2024-46周-周一】

文章目录 1、子网掩码有什么作用,和IP地址是什么关系,利用子网掩码可以获取哪些信息?2、已知一个IP地址是192.168.1.1,子网掩码是255.255.255.0,求其网络地址3、已知某主机的IP地址是192.168.100.200,子网掩…

arkUI:遍历数据数组动态渲染(forEach)

arkUI:遍历数据数组动态渲染(forEach) 1 主要内容说明2 相关内容2.1 ForEach 的基本语法2.2 简单遍历数组2.2 多维数组遍历2.4 使用唯一键2.5 源码1的相关说明2.5.1 源码1 (遍历数据数组动态渲染)2.5.2 源码1运行效果 …

Ue5 umg学习(一)

学习视频资料链接 2、UI编辑界面_哔哩哔哩_bilibili 打开ue5虚幻引擎 创建新的文件夹UI,在这个文件夹里写东西 点击停靠在布局中 双击点进UI文件夹 右键用户界面,选择控件蓝图 创建控件蓝图,重命名,在名称后面加一个_BP1代表是…

PYNQ 框架 - 中断(INTR)驱动

目录 1. 简介 2. 分析 2.1 Block Design 2.2 AXI Timer 2.2.1 IP 基本信息 2.2.2 IP 地址空间 2.2.3 级联模式 2.2.4 生成/捕获模式 2.3 AXI Interrupt 2.3.1 IP 基本信息 2.3.2 IP 地址空间 2.3.3 相关概念 2.3.4 参数配置 2.3.5 中断确认寄存器 3. PYNQ 代码 …

RAG综述:《A Comprehensive Survey of Retrieval-Augmented Generation (RAG)》

来源于《A Comprehensive Survey of Retrieval-Augmented Generation (RAG): Evolution, Current Landscape and Future Directions》 一、RAG所解决的问题 如何有效地从外部知识源检索相关信息,如何将这些信息无缝地融入到生成文本中,以及如何在保证生…

GitLab 如何跨版本升级?

本分分享 GitLab 跨版本升级的一些注意事项。 众所周知,GitLab 的升级必须要严格遵循升级路径,否则就会出现问题,导致升级失败。因此,在 GitLab 升级之前需要做好两件事情: 当前版本的确认升级路径的确认 极狐GitLa…

aws(学习笔记第十二课) 使用AWS的RDS-MySQL

aws(学习笔记第十二课) 使用AWS的RDS 学习内容: AWS的RDS-MySQL 1. 使用AWS的RDS 什么是RDS RDS就是Relation Database Service的缩写,是AWS提供的托管关系型数据库系统。让用户能够在 AWS Cloud 云中更轻松地设置、操作和扩展关系数据库。 数据库和we…

云原生-docker安装与基础操作

一、云原生 Docker 介绍 Docker 在云原生中的优势 二、docker的安装 三、docker的基础命令 1. docker pull(拉取镜像) 2. docker images(查看本地镜像) 3. docker run(创建并启动容器) 4. docker ps…

Spark 核心概念与宽窄依赖的详细解析

Spark 的介绍与搭建:从理论到实践_spark环境搭建-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交:本地与集群模式全解析-CSDN博客 Spark on YARN:Spark集群模式…

【css】html里面的图片宽度设为百分比,高度要与宽度一样

场景&#xff1a;展示图片列表的时候&#xff0c;原始图片宽高不一致。 外层div的宽度自适应&#xff0c;图片宽度不能固定数值&#xff0c;只能设置百分比。图片高度也不能设置固定数值。 如何让图片的高度与图片的宽度一样呢&#xff1f; html代码 &#xff1a; <div cl…

c#使用COM接口设置excel单元格宽高匹配图片,如何计算?

c#使用COM接口设置excel单元格宽高如何换算 在实际工作中&#xff0c;经常需要在excel中插入图片。并设置单元格与图片对齐。但是excel单元格的宽度和高度使用不同的单位。单元格的宽度以字符宽度为单位&#xff0c;而高度以点为单位。如果按照实际值来设置&#xff0c;例如设…

RHCE web解析、dns配置、firewalld配置实验

RHCE web解析、dns配置、firewalld配置实验 实验一1.清理软件包2.安装软件包3.配置web服务查看默认测试页面报错讲解12 4.安装DNS解析需要的bind软件包5.修改网络配置&#xff0c;查错&#xff0c;修改权限 实验二配置文件haha.confnamed.confnamed.haha 实验一 1、学习方法 重…

JavaEE进阶----SpringMVC(三)---响应的获取

文章目录 1.cookie和session获取1.1servlet写法获取1.2spring获取cookie1.3传统方法获取session1.4sring获取session内容 2.访问静态页面3.一个项目部署多个服务4.responsebody的介绍5.返回html的片段6.不同相应content-type类型6.1text/html类型6.2application-json类型6.3 js…

Chromium 中MemoryMappedFile使用例子c++

文件映射基础介绍参考微软官网&#xff1a; 使用文件映射 - Win32 apps | Microsoft Learn 在文件中创建视图 - Win32 apps | Microsoft Learn 创建命名的共享内存 - Win32 apps | Microsoft Learn 使用大页面创建文件映射 - Win32 apps | Microsoft Learn 从文件句柄获取…

OpenHarmony4.1蓝牙芯片如何适配?触觉智能RK3568主板SBC3568演示

当打开蓝牙后没有反应时&#xff0c;需要排查蓝牙节点是否对应、固件是否加载成功&#xff0c;本文介绍开源鸿蒙OpenHarmony4.1系统下适配蓝牙的方法&#xff0c;触觉智能SBC3568主板演示 修改对应节点 开发板蓝牙硬件连接为UART1&#xff0c;修改对应的节点&#xff0c;路径为…

前端 JS面向对象 原型 prototype

目录 一、问题引出 二、prototype原型对象 三、小结 四、constructor 五、__proto__对象原型 六、原型链 一、问题引出 由于JS的构造函数存在内存浪费问题&#xff1a; function Star(name,age){this.namenamethis.ageagethis.singfunction () {console.log("唱歌&…

生成 Django 中文文档 PDF 版

文章目录 背景克隆 Django 文档和翻译仓库配置 conf.py设置和同步翻译生成 .pot 文件运行 sphinx-intl update复制翻译文件 构建 PDF生成 tex 文件安装 MikTeX生成 PDF Sphinx 生成文档 背景 浏览看到一个帖子&#xff0c;有个评论说可以用 sphinx 构建一个 pdf&#xff0c;正…

mysql 实现分库分表之 --- 基于 MyCAT 的分片策略详解

引言 在我们日常工作的项目中&#xff0c;特别是面向 C 端用户的产品&#xff0c;随着业务量的逐步扩大&#xff0c;数据量也呈指数级增长。为了应对日益增长的数据库压力&#xff0c;数据库优化已成为项目中不可或缺的一环&#xff0c;而分库分表则是海量数据优化方案中的重要…