GolangTodolist

2024年 3月 18日 166.5k 0

前言

作为一名前端工程师,我个人觉得有必要去学一门后端语言,目前的行情越来越差,可能对全栈工程师更加友好一点,毕竟老板可以用一个人的钱,招来两个人,当然了前后端都自己包揽的话确实压力有点大,所以学习后端可以使我们在前端招聘中与竞争对手拉开差距,废话不多说,开搞!

我也是初学者勿喷,有什么问题可以在评论区探讨,谢谢

所需

  • 首先必须安装GO GO下载链接
  • Goland编译器 Goland下载链接
  • MysqlMysql下载链接
  • 最好有一点nodejs写接口的经验 这样学起来还是很轻松的
  • 需求

    做一个增删改查的 Todolist 不要小看一个 Todolist 这里涵盖着业务中最常见的 crud 通过这一个简单的例子来上手Go语言

    分析

    首先我们需要把整体架构设计出来,也就是把文件目录先创建好,然后在对应文件夹下书写我们的业务代码,我们可以把整体项目拆分成四个模块

  • 数据库模块
  • 数据库表结构模块
  • Controller模块 (接收客户端发送的请求并执行对应的回调函数,暂时可以这么理解)
  • Service模块 (与数据库进行交互)
  • todolist/ 
      └── server/ 
        └── db/ 
          └── mysql.go
        └── model/ 
          └── todolist.go
        └── controller/ 
          └── todolist.go
        └── service/ 
          └── todolist.go
        main.go // 入口文件
    

    这个就是我们最终的文件结构

    开发

    我们把模块已经拆分好了,在各自文件夹开发就好了

    基础配置

    在核心功能开发前,我们还需要把基础服务搭建起来

    安装开启本地服务的依赖

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

    开启本地服务

    // 设置响应头允许跨域
    func Cors() gin.HandlerFunc {
        return func(c *gin.Context) {
           c.Header("Access-Control-Allow-Origin", "*")
           c.Header("Access-Control-Allow-Headers", "Content-Type")
           c.Header("Access-Control-Allow-Methods", "GET,POST")
    
           if c.Request.Method == "OPTIONS" {
              c.JSON(http.StatusOK, "")
              c.Abort()
              return
           }
    
           c.Next()
        }
    }
    
    func main() {
        r := gin.Default()
        r.Use(Cors())
    
        if err := r.Run(":8080"); err != nil {
           fmt.Printf("Server is failed running at 8080")
        }
    }
    

    定义数据库表结构

    model/todolist.go 中编写

    package model
    
    import (
        "database/sql"
        "time"
    )
    // gorm给我们提供的默认字段
    type GormModel struct {
        ID        uint         `json:"id" gorm:"primarykey"`
        CreatedAt time.Time    `json:"created_at"`
        UpdatedAt time.Time    `json:"updated_at"`
        DeletedAt sql.NullTime `json:"deleted_at" gorm:"index"`
    }
    
    // todolist的表结构
    type Todolist struct {
        GormModel
        Content     string `json:"content"`
        IsCompleted bool   `json:"is_completed"`
    }
    

    json:"XXX"代表这个字段在JSON格式中字段名,因为平时的习惯都是以小写开头,但是因为go语言的原因,
    包与包之间,只能调用以大写开头的,否则无法使用外部成员

    连接mysql

    db/mysql.go 中编写,这次使用的是gorm进行数据库的连接 官方文档

    首先安装依赖

    go get -u gorm.io/gorm

    image.png

    package db
    
    import (
        "gorm.io/driver/mysql"
        "gorm.io/gorm"
    )
    
    func Connect(dbName string) *gorm.DB {
        // refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
        // user pass 填入你mysql的账号密码
        dsn := "user:pass@tcp(127.0.0.1:3306)/" + 
        dbName + "?charset=utf8mb4&parseTime=True&loc=Local"
        db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    
        if err != nil { // 处理错误
           panic(err.Error())
        }
    
        return db
    }
    

    这样我们就得到了数据库的实例对象,可以开始操作数据库啦,不过在操作数据库前,还需要在入口文件进行配置噢~

    在 main.go 中编写

    db.AutoMigrate把我们先前定义的表结构传递进去model/todolist.go中的Todolist,那么我们启动服务后,数据库就会创建一张表出来了

    // 设置响应头允许跨域
    func Cors() gin.HandlerFunc {
        return func(c *gin.Context) {
           c.Header("Access-Control-Allow-Origin", "*")
           c.Header("Access-Control-Allow-Headers", "Content-Type")
           c.Header("Access-Control-Allow-Methods", "GET,POST")
    
           if c.Request.Method == "OPTIONS" {
              c.JSON(http.StatusOK, "")
              c.Abort()
              return
           }
    
           c.Next()
        }
    }
    
    func main() {
    
        r := gin.Default()
        // 连接表名为study的数据库
        db := db.Connect("study")
        // 建立数据库映射表
        db.AutoMigrate(&model.Todolist{})
        // 使用中间件
        r.Use(Cors())
    
        if err := r.Run(":8080"); err != nil {
           fmt.Printf("Server is failed running at 8080")
        }
    }
    

    我们可以通过运行main函数来调试我们的代码是否成功

    image.png

    成功的示例: (这里我使用的是navicat)

    image.png

    数据库中会多了一张todolist表,里面的字段跟我们写的表结构是一一对应的,如果你们的情况跟我一样证明已经成功了!恭喜!!!

    编写sql

    service/mysql.go 中编写,这里我们把增删改查的方法写好供外面使用

    这里就不一一赘述了,可能会有点啰嗦,大概解释一下数据库实例的方法,详情可以到gorm官方文档查看

  • Order 排序
  • Find 把我们创建的属性引用传递进去,我们就可以得到查询出来的数据
  • Create 添加
  • Model 传递定义的表结构 指定表查询
  • Where 根据关键词查询
  • Update 修改/更新
  • Select 选择属性
  • Scan 将搜索到的值 赋值到我们传递进去的属性 与Find类似
  • ...
  • package service
    
    import (
        "gorm.io/gorm"
        "server/server/model"
    )
    
    type Todolist struct {
        *gorm.DB
    }
    
    func (list *Todolist) GetList() []model.Todolist {
        var todos []model.Todolist
        list.Order("id desc").Find(&todos)
    
        return todos
    }
    
    func (list *Todolist) AddTodo(content string) model.Todolist {
        var todo = model.Todolist{
           Content:     content,
           IsCompleted: false,
        }
    
        list.Create(&todo)
        return todo
    }
    
    func (list *Todolist) ToggleTodo(id uint) uint {
        var completed bool
        list.Model(&model.Todolist{}).Where("id = ?", id).Select("is_completed").Scan(&completed)
        list.Model(&model.Todolist{}).Where("id = ?", id).Update("is_completed", !completed)
    
        return id
    }
    
    func (list *Todolist) DeleteTodo(id uint) uint {
        list.Delete(&model.Todolist{}, id)
    
        return id
    }
    

    编写controller

  • Todolist 里面包含了所有增删改查的数据库操作
  • PostBody 是Post请求体的类型,后面用于获取请求体数据
  • ShouldBindJSON 是一个函数我们把定义好的结构传入,即可获得请求体的数据
  • type Todolist struct {
        service.Todolist
    }
    
    type PostBody struct {
        Id      uint
        Content string
    }
    
    func (list *Todolist) List(c *gin.Context) {
        todos := list.GetList()
        c.JSON(http.StatusOK, gin.H{
           "code": 200,
           "msg":  "ok",
           "data": todos,
        })
    }
    
    func (list *Todolist) Add(c *gin.Context) {
        var body PostBody
        c.ShouldBindJSON(&body)
        todo := list.AddTodo(body.Content)
        fmt.Println("body", body)
        fmt.Println("todo", todo)
    
        c.JSON(http.StatusOK, gin.H{
           "code": 200,
           "msg":  "ok",
           "data": todo,
        })
    
    }
    
    func (list *Todolist) Toggle(c *gin.Context) {
        var body PostBody
        c.ShouldBindJSON(&body)
    
        id := list.ToggleTodo(body.Id)
        c.JSON(http.StatusOK, gin.H{
           "code": 200,
           "msg":  "ok",
           "data": id,
        })
    }
    
    func (list *Todolist) Delete(c *gin.Context) {
        var body PostBody
        c.ShouldBindJSON(&body)
    
        id := list.DeleteTodo(body.Id)
        c.JSON(http.StatusOK, gin.H{
           "code": 200,
           "msg":  "ok",
           "data": id,
        })
    }
    

    处理请求

    回到我们的 main.go 入口文件,把增删改查的接口定义好

    这里我们做的就是依赖注入

    • service是操作数据库的所以依赖数据库实例,我们只需要把db传入即可
    • controller就是依赖service中的方法,所以传入todolistService
    // main.go
    
    ...
    // service
    todolistService := service.Todolist{
        DB: db,
    }
    
    // controller
    todolistController := controller.Todolist{
        Todolist: todolistService,
    }
    
    // 获取列表
    r.GET("/list", todolistController.List)
    // 添加
    r.POST("/add", todolistController.Add)
    // 切换完成状态
    r.POST("/toggle", todolistController.Toggle)
    // 删除
    r.POST("/delete", todolistController.Delete)
    
    ...
    

    测试

    这里我使用的是postman进行接口的测试

  • list 通过访问 localhost:8080/list 得到我们所有的结果,目前为空
  • image.png

  • add 通过访问 localhost:8080/add 记得选择POST请求
  • image.png

    数据库中就多了一条记录
    image.png

  • toggle 通过访问 localhost:8080/toggle 记得选择POST请求
  • image.png

  • delete 通过访问 localhost:8080/delete 记得选择POST请求
  • image.png

    如果结果跟我一样的话,证明你已经掌握了简单的 crud 啦

    结尾

    如果有以下问题或其他问题可以在评论区询问我哦~!

  • Goland编译器无法运行代码
  • Goland无法安装依赖
  • Go安装失败
  • ......
  • 相关文章

    Oracle如何使用授予和撤销权限的语法和示例
    Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
    下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
    社区版oceanbase安装
    Oracle 导出CSV工具-sqluldr2
    ETL数据集成丨快速将MySQL数据迁移至Doris数据库

    发布评论