Go之Web急速入门Gin+Gorm框架

news2024/11/17 7:47:47

简介

只作为快速入门、了解Go的Gin+Gorm框架的demo,不能作为企业级开发。
详细用法请看官网
《Gin官网》
《Gorm官网》

使用GoLand创建Go项目(默认modules)

go版本1.22.2
需要设置代理下载go相关软件包,否则软件包可能无法下载。

https://goproxy.cn

在这里插入图片描述

目录结构

在这里插入图片描述
go.mod就是管理相关软件的版本信息,如果你学习过Java,可以简单理解mod就是maven、gradle等构建工具

安装 Gin + Gorm 软件包

在这里插入图片描述

控制台执行以下三条命令,否则启动会报错。
gin web框架
gorm orm框架
gorm mysql 数据库驱动

go get -u github.com/gin-gonic/gin
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql

创建mysql数据库

在这里插入图片描述

创建main.go文件

go有且仅有一个main函数,这个是跟java不太一样的地方,java是允许有多个main函数的。

//包的概念
package main

//引入的包路径
import (
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"net/http"
	"path"
	"time"
)

//定义一个结构体
type UserInfo struct {
	gorm.Model        //gorm模型默认包含 ID、CreatedAt、UpdatedAt、DeletedAt 4个变量
	Username   string `gorm:"index" form:"username" json:"username" binding:"required"`
	Password   string `form:"password" json:"password" binding:"required"`
}

// 自定义 gin 中间件 MyHandlerFunc
func MyHandlerFunc(invoke bool) gin.HandlerFunc {
	return func(c *gin.Context) {
		if invoke {
			fmt.Println("请求开始......")
			start := time.Now()
			//在请求上下文中设置值,后续的处理函数可以获取到该值
			c.Set("token", "1")
			token, ok := c.Get("token")
			if !ok {
				c.JSON(http.StatusUnauthorized, gin.H{
					"code":    http.StatusUnauthorized,
					"message": "未授权",
				})
				return
			}
			fmt.Printf("token =  %v\n", token)
			c.Next()
			//c.Abort()表示阻止代码继续往下执行
			//c.Abort()
			//计算请求耗时
			cost := time.Since(start)
			fmt.Println("请求耗时:", cost)
			fmt.Println("请求结束......")
		} else {
			c.Next()
		}
	}
}

//main函数
func main() {
	//0.在控制台输入 go get -u github.com/gin-gonic/gin 安装 Gin 软件包
	//返回默认路由引擎
	r := gin.Default()

	//指定用户使用GET请求访问/hello,并执行匿名函数,返回JSON格式map[string]的数据
	//1.返回map(一般用于临时返回,不推荐)
	r.GET("/map", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "Hello World",
		})
	})

	/*
		2.返回结构体【推荐】(类似java中的对象,但是首字母必须大写,否则无法进行序列化和反序列化)
		以及灵活使用tag来对结构体进行定制化操作
	*/
	type Person struct {
		//后面写`json:"name"`表示如果以json返回,则变量名使用name
		Name    string `json:"name"`
		Message string `json:"message"`
		Age     int    `json:"age"`
	}

	r.GET("/struct", func(c *gin.Context) {
		data := Person{"Meta39", "Java 学习 Go", 25}
		c.JSON(http.StatusOK, data)
	})

	//3.请求地址携带参数的请求【不推荐】(主要使用c.Query,访问:localhost:8080/query?name=Meta39&age=25,浏览器返回Meta39,控制台输出age: 25)
	r.GET("/query", func(c *gin.Context) {
		name := c.Query("name")
		age := c.Query("age")
		c.JSON(http.StatusOK, gin.H{
			"name": name,
		})
		fmt.Printf("age: %s\n", age)
	})

	//4.获取URL路径参数【推荐】(根据用户ID查询用户信息,访问:localhost:8080/user/1)
	//relativePath也可以是/user/:id/:age,多个组合
	r.GET("/user/:id", func(c *gin.Context) {
		id := c.Param("id")
		c.JSON(http.StatusOK, gin.H{
			"id":   id,
			"name": "Meta39",
			"age":  25,
			"sex":  "Man",
		})
	})

	//5.参数绑定ShouldBind【推荐】(访问:localhost:8080/shouldBind,在body {"username": "mata","password": "123456"})
	r.POST("/shouldBind", func(c *gin.Context) {
		//声明UserInfo类型的变量u
		var u UserInfo
		//& 类似于 Spring @RequestBody 注解
		err := c.ShouldBind(&u)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": err.Error(),
			})
			return
		}
		fmt.Printf("%+v\n", u)
		c.JSON(http.StatusOK, gin.H{
			"success": "ok",
		})
	})

	//6.文件上传
	r.POST("/upload", func(c *gin.Context) {
		//从请求中读取文件
		f, err := c.FormFile("file")
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": err.Error(),
			})
			return
		}
		//将读取的文件保存到本地
		dst := path.Join("./", f.Filename)
		_ = c.SaveUploadedFile(f, dst)
		c.JSON(http.StatusOK, gin.H{
			"success": "ok",
		})
	})

	//7.处理404
	r.NoRoute(func(c *gin.Context) {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "404 Not Found",
			"data":    nil,
		})
	})

	//8.路由组【支持嵌套】(类似SpringBoot里的@RequestMapping)
	userGroup := r.Group("/users")
	{
		//根据用户id查询用户
		userGroup.GET("/:id", func(c *gin.Context) {
			id := c.Param("id")
			c.JSON(http.StatusOK, gin.H{
				"id":   id,
				"name": "Meta39",
			})
		})
		//创建用户
		userGroup.POST("/", func(c *gin.Context) {
			var u UserInfo
			err := c.ShouldBind(&u)
			if err != nil {
				c.JSON(http.StatusBadRequest, gin.H{
					"error": err.Error(),
				})
			}
			fmt.Printf("创建用户:%+v\n", u)
			c.JSON(http.StatusOK, gin.H{
				"success": "ok",
			})
		})
	}

	//9.定义中间件,一般放到路由组Group(类似Java中的filter过滤器)
	r.GET("/handlerFunc", MyHandlerFunc(true), func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "MyHandlerFunc",
		})
	})

	//10.在控制台输入 go get -u gorm.io/gorm 安装 gorm 软件包
	//11.在控制台输入 go get -u gorm.io/driver/mysql 安装 gorm mysql 数据库驱动软件包
	dsn := "root:123456@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
	db, gormErr := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if gormErr != nil {
		panic("failed to connect database")
	}

	// 迁移 schema
	_ = db.AutoMigrate(&UserInfo{})
	var userInfo UserInfo
	// Create
	db.Create(&UserInfo{Username: "Meta39", Password: "123456"})
	// Read
	db.First(&userInfo, 1)                        // 根据整型主键查找
	db.First(&userInfo, "username = ?", "Meta39") // 查找 username 字段值为 Meta39 的记录

	// Update - 将 userInfo 的 Password 更新为 654321
	db.Model(&userInfo).Update("Password", "654321")
	// Update - 更新多个字段
	db.Model(&userInfo).Updates(UserInfo{Username: "Meta", Password: "123"}) // 仅更新非零值字段
	db.Model(&userInfo).Updates(map[string]interface{}{"Username": "Meta1", "Password": "234"})

	// Delete - 删除 userInfo(默认:软删除,即:打上删除标志,如在deleted_at填充时间,表示这条数据已经被删除了)
	//db.Delete(&userInfo, 1)
	//永久删除
	//db.Unscoped().Delete(&userInfo, 1)

	//启动服务不指定端口号,则默认:8080
	ginErr := r.Run(":8080")

	//启动异常处理并输出异常信息
	if ginErr != nil {
		fmt.Printf("ginErr:%v\n", ginErr)
		return
	}

}

控制台执行

go run .\main.go

打开浏览器访问localhost:8080/map会输出JSON格式的Hello World
数据库会有一条id = 1的记录

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

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

相关文章

unity2D游戏开发06稳定,材质,碰撞器

稳定性 在操控玩家时,我们会发现玩家移动时,摄像头会有抖动,这是摄像机过度精确造成的。 创建名为RoundCameraPos的C#脚本,用Visual Studio打开 代码 using System.Collections; using System.Collections.Generic; using UnityEngine; using Cinemachine;//导入Cinemac…

大模型llama结构技术点分享;transformer模型常见知识点nlp面经

1、大模型llama3技术点 参考:https://www.zhihu.com/question/662354435/answer/3572364267 Llama1-3,数据tokens从1-2T到15T;使用了MHA(GQA缓存);上下文长度从2-4-8K;应用了强化学习对其。 1、pretraini…

【YashanDB知识库】yasdb jdbc驱动集成BeetISQL中间件,业务(java)报autoAssignKey failure异常

问题现象 BeetISQL中间件版本:2.13.8.RELEASE 客户在调用BeetISQL提供的api向yashandb的表中执行batch insert并将返回sequence设置到传入的java bean时,报如下异常: 问题的风险及影响 影响业务流程正常执行,无法获得batch ins…

html css 分页按钮效果

结果展示&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>分页按钮效果</title>&…

Richtek立锜科技微型辅听器系统电源解决方案

立锜科技推出微型辅听器系统电源解决方案&#xff0c;为新型设计提供了关键助力&#xff0c;克服小尺寸的挑战&#xff0c;同时确保系统发挥最佳性能。高效率&#xff1a;低静态电流Buck 转换器具有最佳性能&#xff0c;在 1mA 到 10mA 轻载范围内&#xff0c;效率高达 90&…

{Spring Boot 原理篇} Spring Boot自动装配原理

SpringBootApplication 1&#xff0c;Spring Boot 应用启动&#xff0c;SpringBootApplication标注的类就是启动类&#xff0c;它去实现配置类中的Bean的自动装配 SpringBootApplication public class SpringbootRedis01Application {public static void main(String[] args)…

JVM调优与监控工具概览

JVM调优与监控工具概览 1、JDK自带工具1.1 jconsole1.2 jvisualvm 2、第三方工具2.1 MAT&#xff08;Memory Analyzer Tool&#xff09;2.2 GChisto &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; JVM的性能调优与监控是确保应用稳定运行的…

《华为数据之道》读书笔记六---面向自助消费的数据服务建设

七、从结果管理到过程管理&#xff0c; 从能“看”到能“管” 1、数据赋能业务运营 数字化运营旨在利用数字化技术获取、管理和分析数据&#xff0c;从而为企业的战略决策与业务运营提供可量化的、科学的支撑。 数字化运营归根结底是运营&#xff0c;旨在推动运营效率与能力的…

LInux工具(2)

目录 1.关于底行模式的一个设置 1.1设置行号 1.2取消行号 2.简单vim配置 2.1简单认识 2.2配置选项 2.3其他说明 3.库的引入 3.1背景知识 3.2对应指令 3.3相关介绍 3.4.o文件和库的链接 3.5静态库的安装和测试 3.6动静态库对比 1.关于底行模式的一个设置 1.1设置行…

【Jupyter Notebook】一文详细向您介绍 【重启内核】

【Jupyter Notebook】一文详细向您介绍 【重启内核】 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕…

MySQL InnoDB事务隔离和并发控制面试题详解

1. 为什么 MySQL 使用 B+ 树作为索引而不是 B 树? MySQL 选择使用 B+ 树作为索引主要有以下几个原因: 减少 IO 次数,提高效率:B+ 树的所有数据都存储在叶子节点,非叶子节点只存储索引,树的高度较低,因此查找路径较短,减少了磁盘 IO 次数。查询效率更加稳定:由于数据仅…

模拟噪声常见误区

简介 噪声是模拟电路设计的一个核心问题&#xff0c;它会直接影响能从测量中提取的信息量&#xff0c;以及能获取所需信息的经济成本。遗憾的是&#xff0c;关于噪声有许多混淆和误导的信息&#xff0c;可能导致性能不佳、高成本的过渡设计或资源使用效率低下。 1 降低电路中的…

基于Vue开发的前端系统中寻找后端API及其参数

前言 在日常渗透工作中&#xff0c;常常遇到后台系统&#xff0c;且有相当一部分是自研开发的系统&#xff0c;没有源代码&#xff0c;没有弱口令漏洞&#xff0c;也没有swagger、webpack泄露等。幸运的是&#xff0c;这些系统几乎都是前后端分离的架构&#xff0c;而我发现使…

opencascade AIS_ManipulatorOwner AIS_MediaPlayer源码学习

前言 AIS_ManipulatorOwner是OpenCascade中的一个类&#xff0c;主要用于操纵对象的交互控制。AIS_ManipulatorOwner结合AIS_Manipulator类&#xff0c;允许用户通过可视化工具&#xff08;如旋转、平移、缩放等&#xff09;来操纵几何对象。 以下是AIS_ManipulatorOwner的基…

算法力扣刷题记录 五十九【450.删除二叉搜索树中的节点】

前言 记录 五十八【701.二叉搜索树中的插入操作】保证插的新节点在叶子节点的位置&#xff0c;如此实现递归。 那么【450.删除二叉搜索树中的节点】删除如何实现&#xff1f;还有简单的方法吗&#xff1f; 一、题目阅读 给定一个二叉搜索树的根节点 root 和一个值 key&#…

VINS-Fusion 回环检测pose_graph_node

VINS-Fusion回环检测,在节点pose_graph_node中启动。 pose_graph_node总体流程如下: 重点看process线程。 process线程中,将订阅的图像、点云、位姿时间戳对齐,对齐后分别存入image_msg、point_msg、pose_msg。pose_msg为VIO后端优化发布的位姿。 一、创建关键帧keyFram…

Clion开发STM32——移植FreeModbus

STM32型号 &#xff1a;STM32H743VIT6 FreeModbus版本 &#xff1a;1.6 使用工具&#xff1a;stm32cubeMX&#xff0c;Clion 使用STM32作从机&#xff0c;模式&#xff1a;RTU 网上用keil的比较多&#xff0c;用Clion的比较少&#xff0c;如果你也用Clion&#xff0c;那么希望…

数据结构之队列详解

1.队列的概念以及结构 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFo(Frist in Frist out)的特性 入队列&#xff1a;进行插入才操作的一端称为队尾 出队列&#xff1a;进行删除操作的一…

phpstudy下载使用以及搭建本地SQL labs靶场

一&#xff0c;PHP study 小皮面板(phpstudy) - 让天下没有难配的服务器环境&#xff01; (xp.cn) 1&#xff0c;下载。 根据自己电脑系统下载对应的版本。 双击exe文件运行 选择下载目录&#xff08;路径不能有中文名&#xff09;。 2&#xff0c;使用。 启动阿帕奇和MySQ…

Pytorch使用教学8-张量的科学运算

在介绍完PyTorch中的广播运算后&#xff0c;继续为大家介绍PyTorch的内置数学运算&#xff1a; 首先对内置函数有一个功能印象&#xff0c;知道它的存在&#xff0c;使用时再查具体怎么用其次&#xff0c;我还会介绍PyTorch科学运算的注意事项与一些实用小技巧 1 基本数学运算…