練習題 3
step 0. install
$ go get -u github.com/gin-gonic/gin
$ go mod vendor
step 1. Gin basic
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"})
}
)
r.Run() // @ 0.0.0.0:8080
}
step 2. Prototype (without db)
|- main.go
|- /todos
|- models.go
|- routers.go
main.go
package main
import (
"github.com/JasonYCHuang/todo/todos"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
api := r.Group("/api")
v1 := api.Group("/v1")
todosRegister := v1.Group("/todos")
{
todosRegister.GET("/", todos.GetTodosHandler)
todosRegister.GET("/:id", todos.GetTodoHandler)
todosRegister.POST("/", todos.CreateTodoHandler)
todosRegister.PUT("/:id", todos.UpdateTodoHandler)
todosRegister.DELETE("/:id", todos.DeleteTodoHandler)
}
r.Run(":3001")
}
todos/routers.go
package todos
import (
"github.com/gin-gonic/gin"
"net/http"
)
func GetTodosHandler(c *gin.Context) {
tds, err := findAllTodos()
if err != nil {
c.AbortWithStatus(404)
return
}
c.JSON(http.StatusOK, gin.H{"todos": tds})
}
func GetTodoHandler(c *gin.Context) {
id := c.Param("id")
td, err := findOneTodo(id)
if err != nil {
c.AbortWithStatus(404)
return
}
c.JSON(http.StatusOK, gin.H{"todo": td})
}
func CreateTodoHandler(c *gin.Context) {
var td TodoModel
c.BindJSON(&td)
td.Create()
c.JSON(http.StatusOK, gin.H{"todos": td})
}
func UpdateTodoHandler(c *gin.Context) {
id := c.Param("id")
td, err := findOneTodo(id)
if err != nil {
c.AbortWithStatus(404)
return
}
c.BindJSON(&td)
if err = td.Update(); err != nil {
c.AbortWithStatus(404)
return
}
c.JSON(http.StatusOK, gin.H{"todo": td})
}
func DeleteTodoHandler(c *gin.Context) {
id := c.Param("id")
td, err := findOneTodo(id)
if err != nil {
c.AbortWithStatus(404)
return
}
td.Delete()
c.JSON(http.StatusOK, gin.H{"todo": td})
}
todos/models.go
package todos
import (
"errors"
"strconv"
)
type TodoModel struct {
ID int
Title string
}
var store []TodoModel
var inc int
func findAllTodos() (tds []TodoModel, err error) {
tds = store
return
}
func findOneTodo(id string) (td TodoModel, err error) {
if iid, err := strconv.Atoi(id); err == nil {
for _, v := range store {
if v.ID == iid {
return v, err
}
}
}
err = errors.New("Todo not found!")
return
}
func (td *TodoModel) Create() {
td.ID = inc
inc++
store = append(store, *td)
}
func (td *TodoModel) Update() (err error) {
counter := 0
for _, v := range store {
if v.ID == td.ID {
break
}
counter++
}
store = append(
store[:counter],
append([]TodoModel{*td}, store[counter+1:]...)...,
)
return
}
func (td *TodoModel) Delete() {
counter := 0
for _, v := range store {
if v.ID == td.ID {
break
}
counter++
}
store = append(store[:counter], store[counter+1:]...)
}
step 3. handler register
main.go
func main() {
...
api := r.Group("/api")
v1 := api.Group("/v1")
todos.TodosRegister(v1.Group("/todos"))
...
}
router.go
func TodosRegister(router *gin.RouterGroup) {
router.GET("/", getTodosHandler)
router.GET("/:id", getTodoHandler)
router.POST("/", createTodoHandler)
router.PUT("/:id", updateTodoHandler)
router.DELETE("/:id", deleteTodoHandler)
}
step 4. serializer
serializers.go
package todos
import (
"github.com/gin-gonic/gin"
)
type TodoSerializer struct {
C *gin.Context
TodoModel
}
type TodosSerializer struct {
C *gin.Context
TodoModels []TodoModel
}
type TodoResponse struct {
ID int `json:"id"`
Title string `json:"title"`
}
func (s *TodoSerializer) Response() (rsp TodoResponse) {
m := s.TodoModel
rsp = TodoResponse{
ID: m.ID,
Title: m.Title,
}
return
}
func (s *TodosSerializer) Response() (rsp []TodoResponse) {
for _, v := range s.TodoModels {
serializer := TodoSerializer{s.C, v}
rsp = append(rsp, serializer.Response())
}
return
}
routers.go
func getTodosHandler(c *gin.Context) {
...
serializer := TodosSerializer{c, tds}
c.JSON(http.StatusOK, gin.H{"todos": serializer.Response()})
}
step 5. gorm
main.go
package main
import (
"github.com/JasonYCHuang/todo/common"
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
)
func Migrate(db *gorm.DB) {
db.AutoMigrate(&todos.TodoModel{})
}
func main() {
db := common.Init()
Migrate(db)
defer db.Close()
...
}
todos/model.go
package todos
import (
"github.com/JasonYCHuang/todo/common"
"github.com/jinzhu/gorm"
"strconv"
)
type TodoModel struct {
gorm.Model
Title string
}
func findAllTodos() (tds []TodoModel, err error) {
db := common.GetDB()
err = db.Find(&tds).Error
return
}
func findOneTodo(id string) (td TodoModel, err error) {
maps := make(map[string]interface{})
if idx, err := strconv.Atoi(id); err == nil {
maps["id"] = idx
}
err = td.Get(maps)
return
}
func (td *TodoModel) Get(maps interface{}) (err error) {
db := common.GetDB()
err = db.Where(maps).First(td).Error
return
}
func (td *TodoModel) Create() (err error) {
db := common.GetDB()
err = db.Create(td).Error
return
}
func (td *TodoModel) Update() (err error) {
db := common.GetDB()
err = db.Save(td).Error
return
}
func (td *TodoModel) Delete() (err error) {
db := common.GetDB()
err = db.Delete(td).Error
return
}
common/database.go
package common
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"os"
)
type Database struct {
*gorm.DB
}
var DB *gorm.DB
func Init() *gorm.DB {
db, err := gorm.Open("sqlite3", "./gorm.db")
if err != nil {
fmt.Println("db err: ", err)
}
db.DB().SetMaxIdleConns(10)
//db.LogMode(true)
DB = db
return DB
}
func GetDB() *gorm.DB {
return DB
}
Last updated
Was this helpful?