主要涉及的内容:
- API开发框架
gin-gonic
- ORM框架
gorm
- Go语言
mysql
驱动
依赖包
框架引入 gin
$ go get github.com/gin-gonic/gin@latest
$ go get -u github.com/jinzhu/gorm@latest
$ go get github.com/go-sql-driver/mysql@latest
helloworld
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
// listen and serve on 0.0.0.0:8080
r.Run()
}
路由设计
package main
import "github.com/gin-gonic/gin"
var router = gin.Default()
func init() {
router := gin.Default()
v1 := router.Group("/api/v1/todos")
{
v1.POST("/", createTodo)
v1.GET("/", fetchAllTodo)
v1.GET("/:id", fetchSingleTodo)
v1.PUT("/:id", updateTodo)
v1.DELETE("/:id", deleteTodo)
}
}
数据库设计
drop database if exists demo;
create database demo charset='utf8';
use demo;
drop table if exists todo;
create table todo (
primary key(id),
id int not null auto_increment,
title varchar(256) not null default '待办事项',
completed bool not null default 0,
created_at timestamp not null default current_timestamp,
updated_at timestamp not null default current_timestamp,
deleted_at timestamp not null default current_timestamp
) Engine=Innodb;
连接数据库
package main
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
var (
db *gorm.DB
sqlConnection = "golang:1234567890@(114.115.136.205)/demo?charset=utf8&parseTime=True&loc=Local"
)
func init() {
//打开数据库连接
var err error
db, err = gorm.Open("mysql", sqlConnection)
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&todoModel{})
}
模型设计
package main
import "github.com/jinzhu/gorm"
type (
// entity类
todoModel struct {
gorm.Model
Title string `json:"title"`
Completed int `json:"completed"`
}
// response entity
transformedTodo struct {
ID uint `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
}
)
CRUD
package main
import (
"github.com/gin-gonic/gin"
"strconv"
"net/http"
)
// createTodo add a new todo
func createTodo(c *gin.Context) {
completed, _ := strconv.Atoi(c.PostForm("completed"))
todo := todoModel{Title: c.PostForm("title"), Completed: completed}
db.Save(&todo)
c.JSON(http.StatusCreated, gin.H{"status": http.StatusCreated, "message": "Todo item created successfully!", "resourceId": todo.ID})
}
// fetchAllTodo fetch all todos
func fetchAllTodo(c *gin.Context) {
var todos []todoModel
var _todos []transformedTodo
db.Find(&todos)
if len(todos) <= 0 {
c.JSON(http.StatusNotFound, gin.H{"status": http.StatusNotFound, "message": "No todo found!"})
return
}
//transforms the todos for building a good response
for _, item := range todos {
completed := false
if item.Completed == 1 {
completed = true
} else {
completed = false
}
_todos = append(_todos, transformedTodo{ID: item.ID, Title: item.Title, Completed: completed})
}
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": _todos})
}
// fetchSingleTodo fetch a single todo
func fetchSingleTodo(c *gin.Context) {
var todo todoModel
todoID := c.Param("id")
db.First(&todo, todoID)
if todo.ID == 0 {
c.JSON(http.StatusNotFound, gin.H{"status": http.StatusNotFound, "message": "No todo found!"})
return
}
completed := false
if todo.Completed == 1 {
completed = true
} else {
completed = false
}
_todo := transformedTodo{ID: todo.ID, Title: todo.Title, Completed: completed}
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": _todo})
}
// updateTodo update a todo
func updateTodo(c *gin.Context) {
var todo todoModel
todoID := c.Param("id")
db.First(&todo, todoID)
if todo.ID == 0 {
c.JSON(http.StatusNotFound, gin.H{"status": http.StatusNotFound, "message": "No todo found!"})
return
}
db.Model(&todo).Update("title", c.PostForm("title"))
completed, _ := strconv.Atoi(c.PostForm("completed"))
db.Model(&todo).Update("completed", completed)
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "Todo updated successfully!"})
}
// deleteTodo remove a todo
func deleteTodo(c *gin.Context) {
var todo todoModel
todoID := c.Param("id")
db.First(&todo, todoID)
if todo.ID == 0 {
c.JSON(http.StatusNotFound, gin.H{"status": http.StatusNotFound, "message": "No todo found!"})
return
}
db.Delete(&todo)
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "Todo deleted successfully!"})
}
编译打包
将多个go文件打包为一个可执行文件
go build main.go router.go controller.go config.go model.go
如果把所有的代码放在一个文件里面,直接运行即可go build main.go。
单元测试(略)
运维上线
nohup ./main &