前言
作为一名前端工程师,我个人觉得有必要去学一门后端语言,目前的行情越来越差,可能对全栈工程师更加友好一点,毕竟老板可以用一个人的钱,招来两个人,当然了前后端都自己包揽的话确实压力有点大,所以学习后端可以使我们在前端招聘中与竞争对手拉开差距,废话不多说,开搞!
我也是初学者勿喷,有什么问题可以在评论区探讨,谢谢
所需
- 首先必须安装
GO
GO下载链接 Goland
编译器 Goland下载链接Mysql
Mysql下载链接- 最好有一点
nodejs
写接口的经验 这样学起来还是很轻松的
需求
做一个增删改查的 Todolist
不要小看一个 Todolist
这里涵盖着业务中最常见的 crud 通过这一个简单的例子来上手Go
语言
分析
首先我们需要把整体架构设计出来,也就是把文件目录先创建好,然后在对应文件夹下书写我们的业务代码,我们可以把整体项目拆分成四个模块
- 数据库模块
- 数据库表结构模块
- Controller模块 (接收客户端发送的请求并执行对应的回调函数,暂时可以这么理解)
- 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
官方文档查看
- Order 排序
- Find 把我们创建的属性引用传递进去,我们就可以得到查询出来的数据
- Create 添加
- Model 传递定义的表结构 指定表查询
- Where 根据关键词查询
- Update 修改/更新
- Select 选择属性
- Scan 将搜索到的值 赋值到我们传递进去的属性 与Find类似
- ...
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
Todolist
里面包含了所有增删改查的数据库操作PostBody
是Post请求体的类型,后面用于获取请求体数据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进行接口的测试
- list 通过访问
localhost:8080/list
得到我们所有的结果,目前为空
- add 通过访问
localhost:8080/add
记得选择POST请求
数据库中就多了一条记录
- toggle 通过访问
localhost:8080/toggle
记得选择POST请求
- delete 通过访问
localhost:8080/delete
记得选择POST请求
如果结果跟我一样的话,证明你已经掌握了简单的 crud 啦
结尾
如果有以下问题或其他问题可以在评论区询问我哦~!
Goland
编译器无法运行代码Goland
无法安装依赖Go
安装失败- ......