Golang-Todolist

前言

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

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

所需

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

需求

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

分析

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

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

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

开发

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

基础配置

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

安装开启本地服务的依赖

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

开启本地服务

go 复制代码
// 设置响应头允许跨域
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 中编写

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

go 复制代码
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,那么我们启动服务后,数据库就会创建一张表出来了

go 复制代码
// 设置响应头允许跨域
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函数来调试我们的代码是否成功

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

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

编写sql

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

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

  1. Order 排序
  2. Find 把我们创建的属性引用传递进去,我们就可以得到查询出来的数据
  3. Create 添加
  4. Model 传递定义的表结构 指定表查询
  5. Where 根据关键词查询
  6. Update 修改/更新
  7. Select 选择属性
  8. Scan 将搜索到的值 赋值到我们传递进去的属性 与Find类似
  9. ...
go 复制代码
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

  1. Todolist 里面包含了所有增删改查的数据库操作
  2. PostBody 是Post请求体的类型,后面用于获取请求体数据
  3. ShouldBindJSON 是一个函数我们把定义好的结构传入,即可获得请求体的数据
go 复制代码
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
go 复制代码
// 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进行接口的测试

  1. list 通过访问 localhost:8080/list 得到我们所有的结果,目前为空
  1. add 通过访问 localhost:8080/add 记得选择POST请求

数据库中就多了一条记录

  1. toggle 通过访问 localhost:8080/toggle 记得选择POST请求
  1. delete 通过访问 localhost:8080/delete 记得选择POST请求

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

结尾

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

  1. Goland编译器无法运行代码
  2. Goland无法安装依赖
  3. Go安装失败
  4. ......
相关推荐
程序员岳焱几秒前
16.Java Annotation注解:元数据与代码增强
java·后端·编程语言
瀚海澜生2 分钟前
redis系列(2)——AOF日志和RDB快照
后端
ChicagoTypewriter4 分钟前
MySQL用户和授权
mysql
面朝大海,春不暖,花不开1 小时前
Spring Security默认配置覆盖指南
java·后端·spring
圈圈编码1 小时前
悲观锁和乐观锁
java·开发语言·sql·mysql
Java技术小馆2 小时前
打印高质量日志的10条军规
java·后端·面试
学习中的码虫2 小时前
MySQL提升
数据库·mysql
陈随易3 小时前
Element Plus 2.10.0 重磅发布!新增Splitter组件
前端·后端·程序员
陈随易3 小时前
2025年100个产品计划之第11个(哆啦工具箱) - 像哆啦A梦口袋一样丰富的工具箱
前端·后端·程序员
PetterHillWater3 小时前
Automa-RPA实现京东商品自动搜索
后端