前端视角下的Go语法学习:demo-crud 实现增删改查

今日话题

基于 go + gin 实现增删改查,仅仅只是提供接口不涉及数据库增删改查

作者:云层上的光

时间:2024年6月22日 10时15分14秒

主线任务

一、项目创建

1、创建 demo-crud 文件夹

2、编辑器打开 demo-crud 项目,提示设置 go sdk,这里我设置了 1.22.4

3、声明 go.mod 文件

go mod init github.com/chuxin-cs/demo-crud

二、实现增删改查

1、新建 main.go 入口文件,修改 package 为 main

2、添加 main 方法

package main

import "fmt"

func main() {
	fmt.Println("demo-crud...")
}

3、提供 增删改查 方法

package main

import "fmt"

// 增
func add() {
	fmt.Println("add")
}
// 删
func del() {
	fmt.Println("del")
}
// 改
func edit() {
	fmt.Println("edit")
}
// 查
func getList() {
	fmt.Println("getList")
}
func main() {
	fmt.Println("demo-crud...")
	add()
	del()
	edit()
	getList()
}

4、输出打印

三、gin 实现增删改查

1、安装 gin 包,如果遇到报错看 支线任务一

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

2、编写 gin 代码

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
)

// 主函数,程序入口
func main() {
	// 打印信息,标记示例启动
	fmt.Println("demo-crud...")

	// 初始化Gin框架,默认装载中间件
	r := gin.Default()

	// 定义GET请求的路由"/add",处理函数接收一个gin.Context上下文参数
	r.GET("/add", func(c *gin.Context) {
		// 向发送请求的客户端响应状态码200(成功)和字符串"add"
		c.String(200, "add")
	})

	// 启动服务器,监听9000端口
	// 前端可以通过访问"http://localhost:9000/add"来与这个接口进行交互
	r.Run(":9000")
}

3、改造回调函数,完成增删改查

package main

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

// 增
func add(c *gin.Context) {
	c.String(200, "add")
}
// 删
func del(c *gin.Context) {
	c.String(200, "del")
}
// 改
func edit(c *gin.Context) {
	c.String(200, "edit")
}
// 查
func getList(c *gin.Context) {
	c.String(200, "getList")
}

func main() {
	r := gin.Default()
	r.GET("/add", add)
	r.GET("/del", del)
	r.GET("/edit", edit)
	r.GET("/getList", getList)
	// 运行在 9000 端口
	r.Run(":9000")
}

四、改造 gin 目录结构

1、新建 router 文件夹,然后再新建 index.go 文件

代码如下:

package router

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

// Add 增
func Add(c *gin.Context) {
    c.String(200, "add")
}

// Del 删
func Del(c *gin.Context) {
    c.String(200, "del")
}

// Edit 改
func Edit(c *gin.Context) {
    c.String(200, "edit")
}

// GetList 查
func GetList(c *gin.Context) {
    c.String(200, "getList")
}

2、main.go 中改造

代码如下:

package main

import (
	"github.com/chuxin-cs/demo-crud/router"
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.GET("/add", router.Add)
	r.GET("/del", router.Del)
	r.GET("/edit", router.Edit)
	r.GET("/getList", router.GetList)
	// 运行在 9000 端口
	r.Run(":9000")
}

3、主入口程序中 其实不应该写这些代码,后续逻辑涉及到要用结构体,所以留到下期再写 TODO

支线任务

一、下载 gin 依赖失败

go 的插件包需要从 github上下载,网络问题这里就不多提了

其他语言都一样,我们前端的 npm 仓库在国外,依赖下载也会存在失败的情况,所以会通过设置淘宝镜像代理方案解决:

npm config set registry https://registry.npmmirror.com

所以 go 也是一样的,会存在依赖下载失败,以下是go 的通用解决办法:

1、Go modules 是 Go 1.11 版本引入的包管理工具,用于管理和版本控制项目的依赖项,

  • 网上这么说还是不是太明白,先设置吧,后续再研究 TODO
go env -w GO111MODULE=on

2、配置 proxy 代理,这一步操作和前端设置镜像是一个道理

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

3、查看配置是否修改成功

go env

4、gin 依赖下载

二、go get 下载依赖包?

1、go 代码中,下载 gin 包,使用 go get 命令

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

2、如果说 go get 是下载包的命令 那么这里的 -u 又是什么呢?

go get -u 命令的作用是用于更新依赖包到最新版本,那不就是说直接给我上最新依赖

那这就等价于前端的 latest 功能,安装axios最新版

npm i -S axios@latest

三、go mod tidy 也是下载依赖?

go mod tidy 是一个用于整理和优化 Go 模块依赖的命令。具体来说,它会执行以下操作:

  1. 移除未使用的依赖:删除 go.mod 文件中声明但在代码中未使用的包。
  2. 添加缺少的依赖:为代码中使用但未在 go.mod 文件中声明的包添加相应的依赖。
  3. 更新 go.sum 文件:确保 go.sum 文件中的校验和与依赖项的一致性。

简单来说,go mod tidy 可以帮助你保持模块依赖的整洁和一致。

1、听着很懵,换前端怎么理解呢,其实相当于前端拿到新项目之后,一把安装依赖的:

npm i

2、那就是说,下载 go 包我就

go get -u 项目包

3、拿到新的 go 项目,我就一把梭

go mod tidy

四、go 程序也存在回调函数,那我就放心了

1、定义 add 方法时,提供了回调函数,那么这块的玩法思路回到了前端的编程思路中

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
)

func main() {
	fmt.Println("demo-crud...")
    r := gin.Default()
	r.GET("/add", func(c *gin.Context) {
		c.String(200, "add")
	})
	// 运行在 9000 端口
	r.Run(":9000")
}

2、改造回调函数

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
)

func add(c *gin.Context){
    c.String(200, "add")
}

func main() {
	fmt.Println("demo-crud...")
    r := gin.Default()

    // 抽离一个 add 方法出去
	r.GET("/add", add)
    
	// 运行在 9000 端口
	r.Run(":9000")
}

五、gin.Default 的作用?

gin.Default() 在 Gin 框架中是一个便捷函数,它的作用是创建一个新的 gin.Engine 实例,并默认注册一些中间件,包括:

  • Logger: 提供请求日志记录。
  • Recovery: 当发生 panic 时自动恢复,避免服务崩溃,并记录 panic 的详细信息,虽然现在还不能完全看懂源码,但是我大致知道这里干了啥

1、简单点理解就是,gin.Default() 大致相当于在 Koa 中做了两件事:

  1. 创建一个新的 Koa 应用实例 (const app = new Koa()😉
  2. 注册了一些基础的中间件,比如错误处理和日志记录,但 Koa 中这些通常需要单独添加(koa需要自己下载插件集成)
const Koa = require("koa");
const Router = require("koa-router");

// 实例化 koa
const app = new Koa();
// 实例化 路由
const router = new Router();

// 定义 get 请求 监听 /add
router.get("/add", (ctx) => {
  ctx.body = {
    key: "hello koa-router",
  };
});

// 监听本地 3000 端口
app.listen(3000, () => {
  console.log("http://localhost:3000");
});

2、功能大致是 koa 的实例 只是 gin 中 还增加了日志等等

六、r.GET 定义 get 请求?

1、好奇 gin 会提供哪些方法出来?

2、提供了 GET POST DELETE PUT,目前代码看不懂没关系,后续一点一点来 先来一个 TODO

3、关于 get 请求传参 和 post 等接口请求传参,再下一期中产出(还在学习中…)

七、函数形参类型 c *gin.Context

1、gin.Context 对应 koa 中的 ctx

2、Context 内部提供了很多参数

八、go 中的 * 和 &

在 Go 语言中,* 通常表示指针。指针是一种存储变量内存地址的数据类型,它允许你直接操作内存中的数据。当你看到 *T 类型时,这意味着它是一个指向类型 T 的值的指针。

代码中出现,这里的 * 啥意思呢?

func Add(c *gin.Context) {
	fmt.Println(c)
	c.String(200, "add")
}

用前端思路来理解,go 中的 * 和 & ,不过目前demo中还没有用到 &

1、JavaScript 中 有原始类型 和 引用类型,这里 * 和下面要说的 引用类型 有关

// 原始类型
var a = 1;

// 2.引用类型
var obj = {name:"1"}
var b = obj;

2、如果此时我们修改了 b ,会不会影响 obj 呢

var obj = {name:"1"}
var b = obj;

// 尝试修改 b
b.name = "b修改name上的值"

// 打印 b
console.log(b)
// 打印 obj
console.log(obj)

3、修改变量 b 会影响到 obj,这个是 JavaScript 的特性

4、那么 go 中是不是也是相同的呢?

package main

import (
	"fmt"
)

// 1、定义了一个 User 结构体 (前端 = 对象 + ts类型)
type User struct {
	Name string
	Age  int
}

func test() {
	fmt.Println("开始===============")

  ///2、使用结构体创建 obj
	var obj = User{Name: "chuXin", Age: 27}
	fmt.Println(obj)

  ///3、将 obj 赋值给 b
	var b = obj

  // 4、修改 b 的
	b.Name = "初心"
	b.Age = 18

  // 打印
	fmt.Println(obj, "111")
  fmt.Println(b, "111")
  
	fmt.Println("结束===============")
}

func main() {
	test()
}

5、启动项目,用调试模式

6、打印的结果,不受影响

7、JavaScript 中 对象赋值给对象,其实赋值的对象的引用地址

var obj = {name:"1"}
// 实际上给的是引用地址,所以操作才会同步修改到obj
var b = obj;

8、那是不是只需要把 go 中的引用地址给到 b 就可以了,这里使用 & 来获取引用地址

9、打印结果:值同步

10、总结:遇到 * 我们就可以理解为拿到了这个属性的值 再后续操作中 内部会收到影响(目前只理解到这一层)

九、r.Run 端口监听运行

1、在 gin 中监听端口和 koa 类似

func main() {
	r := gin.Default()
	r.GET("/getList", func(c *gin.Context){
    c.String(200, "getList")
  })
  
	// 运行在 9000 端口
	r.Run(":9000")
}

2、koa 也是相同代码 只是语法不同,理解了概念就行

const Koa = require("koa");
const Router = require("koa-router");
// 实例化 koa
const app = new Koa();
const router = new Router();
router.get("/add", (ctx) => {
  ctx.body = {
    key: "hello koa-router",
  };
});
// 监听3000端口
app.listen(3000, () => {
  console.log("http://localhost:3000");
});

十、module 包命名规范

一般包命名:github.com/github的名称/包名,以我自己的 github 地址举例:

https://github.com/chuxin-cs 其中的 chuxin-cs 就是对应的 “github的名称”

1、声明 go.mod 文件

go mod init github.com/chuxin-cs/demo-crud

2、此时 go.mod 文件中

3、为了验证上面的规范拿 gin 来举例:

4、那么 module 有什么作用呢?

5、包引入时需要用到 module

代码仓库

https://github.com/chuxin-cs/go-demo/tree/master/demo-crud

往期内容

点击链接查看:https://www.yuque.com/chuxin-cs/it/ge9wybczy0wsq1l1

  • 36
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值