Go language RESTful API development practice
Microservices, serverless architectures are all the rage these days. API development is at the forefront of these topics. Go is faster to develop than Java Spring and an order of magnitude better in performance than PHP. In particular, Go language is very excellent in concurrent convenience and is a language worth paying attention to in 2017. This article introduces development apis using the Go language through a classic Todo application. Accompanying demo code
Main contents involved:
- API Development Framework
gin-gonic
- ORM framework
gorm
- Go mysql driver
Depend on the package
$ go get gopkg.in/gin-gonic/gin.v1
$ go get -u github.com/jinzhu/gorm
$ go get github.com/go-sql-driver/mysql
Copy the code
Interface documentation:
A, Hello World
package main import "github.com/gin-gonic/gin" func main() { r := gin.Default() r.GET("/ping", Func (c *gin.Context) {c.son (200, gin.H{"message": "pong",})}) r.run () // Listen and serve on 0.0.0.0:8080}Copy the code
Route design
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)
}
}
Copy the code
Third, design the database
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 'todo ', 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;Copy the code
Connect to the database
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{}) }Copy the code
5. Model design
Package main import "github.com/jinzhu/gorm" type (// entity class 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"` } )Copy the code
Six, 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!" })}Copy the code
Compile and package
Package multiple GO files into one executable
go build main.go router.go controller.go config.go model.go
Copy the code
- If you put all the code in one file, you can just run it
go build main.go
.
For the sake of presentation, the packaged files are presented here
Viii. Unit Testing (omitted)
Ix. Operation and maintenance on-line
nohup ./main &
Copy the code
X. Effect display
Create:
Access to:
Update:
Delete:
The original item of this article is from the original address. However, due to the needs of some localization (no need to climb the wall), a major change was made.