前端视角下的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 模块依赖的命令。具体来说,它会执行以下操作:
- 移除未使用的依赖:删除 go.mod 文件中声明但在代码中未使用的包。
- 添加缺少的依赖:为代码中使用但未在 go.mod 文件中声明的包添加相应的依赖。
- 更新 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 中做了两件事:
- 创建一个新的 Koa 应用实例 (const app = new Koa();)
- 注册了一些基础的中间件,比如错误处理和日志记录,但 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 地址举例:
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
代码仓库
往期内容
点击链接查看:www.yuque.com/chuxin-cs/i…
转载自:https://juejin.cn/post/7384997169171922971