Go Web 开发【Gin 框架快速开发】

news2024/10/7 14:24:16

1、Gin Web 快速开发

1.1、环境准备

1.1.1、导入 gin 依赖

这里就叫 gin 依赖了,在 Goland 命令行中输入下面的命令:

go get -u github.com/gin-gonic/gin

1.1.2、设置代理

如果下载失败,最好设置一下代理,在 cmd 命令行中输入下面的命令: 

go env -w GOPROXY=https://goproxy.cn,direct

完了之后再 Goland 这里同样设置启用 environment:

1.2、快速开发

1.2.1、Hello world

package main

import "github.com/gin-gonic/gin"

func main() {
	// 创建一个服务
	ginServer := gin.Default()

    // todo Go语言中的处理请求方法都是函数式编程:第一个参数是请求地址 第二个请求是函数
	// 访问地址,处理请求
	ginServer.GET("/hello", func(context *gin.Context) {
		context.JSON(200,gin.H{"msg":"hello world"})
	})

    // 设置服务器端口
	ginServer.Run(":8082") // 默认 8080
}

        上面,我们首先得到了 ginServer ,然后直接通过函数式编程,给 GET 请求 "/hello" 设置处理函数:直接返回给前端一段 JSON 数据。

        这个返回格式和我们之前学习的 SpringBoot 是不谋而合的,它们都会返回一个状态码和一段任意类型的信息(在 SpringBoot 中是 Object,在这里是 any 类型)。

启动程序,访问 localhost:8082:

1.2.2、给网页设置 icon  

直接在 Goland 命令行输入:go get "github.com/thinkerou/favicon":

 直接在上面的代码基础上添加下面的代码:

import(
    "github.com/thinkerou/favicon"
)

 在 main 方法中添加一行代码即可:

    // 设置网页icon
	ginServer.Use(favicon.New("./sxau.ico"))

测试: 

// todo 新增用户
	ginServer.POST("/user", func(ctx *gin.Context) {
		ctx.JSON(200,gin.H{
			"msg":"新增用户",
		})
	})

1.2.3、给前端响应界面

1、加载 HTML 文件

        有两种方法,一种是加载 html 所在目录下所有文件,一种是加载单个 html 文件:

    // 加载静态页面
	ginServer.LoadHTMLGlob("static/html/*")
	//ginServer.LoadHTMLFiles("static/index.html") // 加载指定的 HTML 文件

2、加载 css、js 
    // 加载资源文件 css、js
	ginServer.Static("/static","./static")

        此外,我们可以看到每次运行,Go 都会把我们的程序打包为一个 exe(windows),在 linux 和 mac 上同样会直接打包为一个可执行文件,所以特别方便!

1.2.4、获取请求中的参数

1)& ?格式
// 1. /user?user_id=xxx&username=xxx 格式
	ginServer.GET("/user", func(ctx *gin.Context) {
		user_id := ctx.Query("user_id")
		username := ctx.Query("username")
		ctx.JSON(http.StatusOK,gin.H{
			"user_id": user_id,
			"username": username,
		})
	})

2)RESTful 风格

SpringBoot 中我们使用 /user/{user_id} 的格式来传递参数,go 语言中我们使用 :user_id 来传递

// 2. /user/user_id/username
	ginServer.GET("/user/:user_id/:username", func(ctx *gin.Context) {
		user_id := ctx.Param("user_id")
		username := ctx.Param("username")
		ctx.JSON(http.StatusOK,gin.H{
			"user_id": user_id,
			"username": username,
		})
	})

1.2.5、序列化数据

把前端发来的数据(已经不是 json 了)转为 json 再返回:

	// todo 前端给后端传递 json
	ginServer.POST("/json", func(ctx *gin.Context) {
		// 从请求体(request.body)获得对象
		// GetRawData() 返回请求体切片[]byte和错误信息err
		data,err := ctx.GetRawData()
		fmt.Println("date => "+string(data))
		fmt.Println("err => ",err)

		var m map[string]interface{}
		// 序列化包装为json数据
		_ = json.Unmarshal(data,&m)

		ctx.JSON(http.StatusOK,m)
	})

1.2.6、获取表单数据

    // todo 新增用户
	ginServer.POST("/user", func(ctx *gin.Context) {

		// 对应表单的input标签的name属性
		username := ctx.PostForm("username")
		password := ctx.PostForm("password")

		ctx.JSON(200,gin.H{
			"msg":"新增用户",
			"username":username,
			"password":password,
		})
	})

 

1.2.5、路由之重定向到首页

重定向的状态码是 301 ! 

    // todo 路由
	ginServer.GET("/test", func(ctx *gin.Context) {
		// 重定向 301
		ctx.Redirect(http.StatusMovedPermanently,"/index")
	})

1.2.6、路由之404页面

    // 404
	ginServer.NoRoute(func(ctx *gin.Context) {
		// 它会自动拼接 static/html/
		ctx.HTML(http.StatusNotFound,"404.html",nil)
	})

1.2.7、路由之路由组

路由组就相当于我们 SpringBoot 中控制器类上面 @RequestMapping 的统一前缀: 

    // 路由组(RESTful 风格)
	book := ginServer.Group("/book")
	{
		// 相当于访问 /book/id
		book.GET("/:id", func(ctx *gin.Context) {

		})
		// 相当于访问 /book/id
		book.DELETE("/:id", func(ctx *gin.Context) {

		})
	}

1.2.8、拦截器(中间件)

在我们的 JavaWeb 项目中叫做拦截器,在 Go 语言的 Web 项目中一般叫中间件。

1、自定义拦截器

        下面自定义一个拦截器,请求参数中必须包含 username ,如果用户名是 admin 则放行,否则阻止。此外,我们可以在拦截器中设置一些全局变量,如果一个请求设置了拦截器,那么就可以在这个请求的处理方法中获取拦截器中设置的参数。

// 自定义go中间件 (相当于Java中的拦截器)
func interceptor() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		// 通过自定义的中间件设置的值,后续都可以通过中间件访问到这个值
		ctx.Set("usersession","user")
		username := ctx.Query("username")
		if username=="admin" {
			ctx.Next() // 放行
		}else {
			ctx.Abort() // 阻止
		}
	}
}
2、注册拦截器 

注意:如果注册之后没有在任何请求方法中使用拦截器,那么将作用于所有拦截器!如果指定了任意一个或多个拦截器,那么将只会作用于这些请求!

// 注册中间件 注册之后未使用的话默认全局使用 如果未注册或者给某个请求使用了这个中间件的话就只对这个请求生效
	ginServer.Use(interceptor())
3、使用拦截器 
// 这里设置了中间件 会先通过拦截器才能继续处理
	ginServer.GET("/index",interceptor(),func(ctx *gin.Context) {

		// 取出中间件爱中的值
		usersession := ctx.MustGet("usersession").(string)
		log.Println("=========> ",usersession)

		//ctx.JSON(200,gin.H{"msg":"返回 json 数据"})
		ctx.HTML(http.StatusOK,"index.html",gin.H{
			"msg":"这是go后端返回的数据",
		})
	})

测试放行:

测试阻止:

1.3、Web 登录验证 Demo

下面做一个简单的用户登录界面验证,结合 MySQL:

1.3.1、登录界面 HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录页面</title>
    <link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<div class="login-container">
    <h2>登录</h2>
    <form method="post" action="/login">
        <label for="username">用户名:</label>
        <input type="text" name="username" required><br><br>

        <label for="password">密码:</label>
        <input type="password" name="password" required><br><br>

        <input type="submit" value="登录">
    </form>
</div>
</body>
</html>

1.3.2、CSS

body {
    font-family: Arial, sans-serif;
    background-color: #f4f4f4;
}

.login-container {
    width: 300px;
    padding: 16px;
    background-color: white;
    border-radius: 5px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

h2 {
    text-align: center;
}

input[type=text], input[type=password] {
    width: 100%;
    padding: 12px 20px;
    margin: 8px 0;
    display: inline-block;
    border: 1px solid #ccc;
    box-sizing: border-box;
}

input[type=submit] {
    width: 100%;
    background-color: #4CAF50;
    color: white;
    padding: 14px 20px;
    margin: 8px 0;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

input[type=submit]:hover {
    background-color: #45a049;
}

1.3.3、Go 数据库查询代码

需要导入 mysql 的包,连接:

package util

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
)

const USERNAME,PASSWORD string = "root","Yan1029."

// todo 公开的方法必须首字母大写才能被其它go文件调用
func Connect(username, password string) *sql.DB {
	db,err := sql.Open("mysql","root:Yan1029.@tcp(127.0.0.1:3306)/go_web?charset=utf8mb4")
	if err != nil {
		println("连接失败",err)
	}
	db.Ping() // 尝试连接数据库
	return db
}
func Close(db *sql.DB)  {
	if db != nil {
		db.Close()
	}
}

type User struct {
	id int
	username string
	password string
}
/**
	查询用户是否已经注册
 */
func HasUser(db *sql.DB,username,password string) bool {
	var user User
	querySql := "SELECT * FROM register_users WHERE username=? AND password=?"
	row := db.QueryRow(querySql,username,password)
	err := row.Scan(&user.id,&user.username,&user.password)
	if err!=nil {
		fmt.Print("查询失败",err)
		return false
	}
	return true
}

1.3.4、Go 请求处理代码

package main

// 导入 gin
import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/thinkerou/favicon"
	"go1/util"
	"net/http"
)


func main() {
	// 创建一个服务
	ginServer := gin.Default()
	// 设置网页icon
	ginServer.Use(favicon.New("./sxau.ico"))

	// 加载静态页面
	ginServer.LoadHTMLGlob("static/html/*")
	//ginServer.LoadHTMLFiles("static/index.html") // 加载指定的 HTML 文件
	// 加载资源文件
	ginServer.Static("/static","./static")

	ginServer.POST("/login", func(ctx *gin.Context) {
		// 获得登录参数
		username := ctx.PostForm("username")
		password := ctx.PostForm("password")
		db := util.Connect(util.USERNAME,util.PASSWORD)
		if util.HasUser(db,username,password) {
			fmt.Println("存在该用户")
			ctx.HTML(http.StatusOK,"home.html",nil)
		}else{
			fmt.Println("不存在该用户")
			ctx.HTML(http.StatusNotFound,"404.html",nil)
		}
		util.Close(db)
	})
	
	// 服务器端口
	ginServer.Run(":8082") // 默认 8080
}

测试:

输入正确的账号密码:

输入错误的账号密码:

总结

        Go 语言开发 Web 应用还是特别简单的,比起 Java 肉眼可见的高效!确实是爽歪歪,下去好好了再去一下 Go 语言的一些基础!

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

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

相关文章

AI智能名片商城小程序:引领企业迈向第三增长极

随着数字化浪潮的席卷&#xff0c;私域流量的重要性逐渐凸显&#xff0c;为企业增长提供了全新的动力。在这一背景下&#xff0c;AI智能名片商城系统崭露头角&#xff0c;以其独特的优势&#xff0c;引领企业迈向第三增长极。 私域流量的兴起&#xff0c;为企业打开了一扇新的销…

UE4 Widget制作搜索框

效果&#xff1a; 一、控件层级结构 1.父控件层级结构 2.子控件层级结构 二、蓝图 1.先清除掉创建子项&#xff08;注意&#xff1a;这里使用的是reverse循环&#xff01;&#xff09; 2.判断是否含有关键字&#xff0c;创建子控件

【MATLAB源码-第201期】基于matlab的黏菌群优化算法(SMA)无人机三维路径规划,输出做短路径图和适应度曲线

操作环境&#xff1a; MATLAB 2022a 1、算法描述 黏菌优化算法&#xff08;Slime Mould Algorithm, SMA&#xff09;是一种新颖的启发式优化方法&#xff0c;其灵感来源于自然界中的真菌——黏菌。这种算法模拟了黏菌在寻找食物时的行为和网络形成策略。在本文中&#xff0c…

基于yolov5实时实例分割

是一个结合了最新技术进展&#xff08;State-of-the-Art, SOTA&#xff09;的实时实例分割项目&#xff0c;基于著名的YOLOv5目标检测架构&#xff0c;并对其进行扩展以实现对图像中每个对象实例的精确像素级分割。以下是该项目的中文介绍&#xff1a; YOLOv5&#xff1a; YOL…

Django-admin单例模式和懒加载

Django-admin单例模式和懒加载 单例模式 class Foo:def __init__(self):self.name "张三"def __new__(cls, *args, **kwargs):empty_object super().__new__(cls)return empty_objectobj1 Foo() obj2 Foo()当我们实例化对象时&#xff0c;就会在内存开一个空间…

RCD吸收电路:开关电源高频干扰的有效消除器

开关电源中除了我们常规介绍的差模噪声源和共模噪声源&#xff0c;还存在一些其它的噪声源也应该解决&#xff0c;这些高频噪声源同样会带来电磁兼容问题&#xff0c;因此我们需要关注。这里介绍两种干扰源&#xff0c;一种是MOS管的通断带来的高频振荡噪声&#xff0c;另一种是…

ES的脑裂现象

目录 0 集群结点的职责1 什么是脑裂现象2 造成脑裂现象的原因2.1 网络问题&#xff08;最常见&#xff09;2.2 主节点负载过大&#xff0c;资源耗尽&#xff0c;别的结点ping不到主节点2.3 主节点JVM内存回收时间过长导致 3 脑裂现象的解决方案3.1 局域网部署3.2 角色分离&…

Redis线程模型及性能优化概述

redis线程模型&#xff1a; 网络模块命令处理 redis的性能&#xff1a; 一个取决于物理内存&#xff0c;另一个是对于socket请求的处理速度。 4.0以前 单线程模式 请求流程&#xff1a;对于一个请求&#xff0c;线程会根据操作产生相应的事件&#xff08;读&#xff0c;写事…

idm线程怎么设置 idm线程数怎么上不去 idm免安装

IDM&#xff08;Internet Download Manager&#xff09;是一款流行的下载管理软件&#xff0c;IDM采用高级的多线程下载技术&#xff0c;可以将下载文件分成多个部分同时下载&#xff0c;从而提高下载速度&#xff0c;它因高效的下载速度和丰富的功能而受到用户的喜爱。接下来&…

探索Jellyfin:支持Android的自由开源的媒体服务器平台

探索Jellyfin&#xff1a;支持Android的自由开源的媒体服务器平台 I. 简介 A. 什么是Jellyfin&#xff1f; Jellyfin是一个自由开源的媒体服务器平台&#xff0c;旨在让用户能够自主管理和流式传输他们的媒体内容。与许多闭源的商业媒体服务器解决方案不同&#xff0c;Jelly…

LT2611UX四端口 LVDS转 HDMI2.0,带音频

描述LT2611UX 是一款面向机顶盒、DVD 应用的高性能 LVDS 至 HDMI2.0 转换器。LVDS输入可配置为单端口、双端口或四端口&#xff0c;具有1个高速时钟通道和3~4个高速数据通道&#xff0c;工作速率最高为1.2Gbps/通道&#xff0c;可支持高达19.2Gbps的总带宽。LT2611UX 支持灵活的…

ubuntu22 部署fastDFS单节点和集群,整合Spring Boot(刚部署成功)

ubuntu22 部署fastDFS单节点和集群 一、先准备1、所需依赖安装2、下载安装包 二、安装FastDFS单节点1、libfastcommon安装1.1、创建软连接 2、安装fastDFS2.1、fastDFS目录简单介绍2.2、创建软连接 3、配置和启动Tracker服务3.1、修改Tracker配置文件3.2、启动Tracker 4、配置和…

xLua热更新解决方案

图中灰色的无法实现热更新&#xff0c;而Lua代码可以打包成AB包&#xff0c;并上传到资源服务器&#xff0c; 当进入游戏检测是否有资源需要更新&#xff0c;需要则会从资源服务器下载。 学习目标 1.导入xLua框架 2.C#调用Lua 3.Lua调用C# 4.xLua热补丁 xLua框架导入和AB…

JAVA系列 小白入门参考资料 继承

目录 1. 为什么需要继承 2. 继承的概念 3. 继承的语法 4. 父类成员访问 4.1 子类中访问父类的成员变量 1. 子类和父类不存在同名成员变量 2. 子类和父类成员变量同名 4.2 子类中访问父类的成员方法 1. 成员方法名字不同 2. 成员方法名字相同 ​5. super关键字 …

使用Visual Studio在CMake项目中链接第三方库(OpenCV为例)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 为什么要链接第三方库&#xff1f; 提高效率&#xff1a;使用第三方库可以加速开发过程&#xff0c;因为你不需要从头开始编写所…

2024.4.25 LoadRunner 测试工具详解 —— Controller Analysis

目录 Controller 的使用 创建场景 Controller 快捷方式创建场景 VUG 针对写好脚本创建场景 场景设计 设计初始化 设计启动机制 设计性能测试脚本的执行时间 设计虚拟用户退出机制 场景运行 添加监控指标至图标格区域 Analysis 的使用 汇总报告 测试报表 吞吐量图 …

消灭AI“耗电巨兽”?暴雨服务器推出液冷节能降耗算力方案

在科技飞速发展的今天&#xff0c;人工智能已成为驱动未来的重要力量。随着AI及大模型技术的进一步普及和应用场景的拓宽&#xff0c;相关算力需求呈指数级增长&#xff0c;大规模的AI训练和推理过程均需消耗大量电力&#xff0c;如同一个巨大的电力黑洞&#xff0c;吞噬着海量…

线阵相机和面阵相机简介

线阵相机 线阵相机&#xff0c;顾名思义就是所探测的物体要在一个很长的界面上。线阵相机的传感器只有一行感光像素&#xff0c;所以线阵相机一般具有非常高的扫描频率和分辨率。 线阵相机特点 线阵相机使用的线扫描传感器通常只有一行感光单元&#xff08;少数彩色线阵使用…

密文域可逆信息隐藏技术综述(上)

加密图像可逆信息隐藏是一种加密原始图像后&#xff0c;在密文图像中可逆地隐藏附加数据&#xff0c;并且在数据提取后&#xff0c;原始图像可以被无损重建的技术。RDH-EI的分类如图1所示。 按对图像的加密方法&#xff0c;现有RDH-EI算法可分为对称加密域和非对称(公钥)加密域…

新手向:HTML进阶

一&#xff0c;列表 列表分为有序列表&#xff0c;无序列表&#xff0c;定义列表三种 1.有序列表 ol 嵌套 li&#xff0c;ol 是有序列表&#xff0c;li 是列表条目 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8">…