github:https://github.com/gin-gonic/gin
0x0 gin简介
gin框架是Go语言进行web开发(api开发,微服务开发)框架中,功能和Martini框架类似的API,但是性能确特别好的一个框架(比Martini快将近40倍吧),所以如果你特别在乎性能,那么Gin会是一个比较好的选择。gin框架主要基于httprouter模块进行实现。gin框架和httprouter都是一个开源的框架。
0x1 Quick start
1. 用module模式创建工程
mkdir web_api
cd web_api
go mod init web_api
2.创建main.go
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() // listen and serve on 0.0.0.0:8080 }
3. 运行
go run main.go
4. 浏览器打开 127.0.0.1:8080
0x2 实践
1.目录结构如下
│ config.yml
│ go.mod
│ go.sum
│ main.go
│ Makefile
│ README.md
├─app
│ app.go
│ handle.go
│ routers.go
│
├─controllers
│ user.go
│
├─models
│ model.go
│ user.go
│
├─routes
│ router.go
│
└─service
user.go
2.主要文件说明
1)app/app.go 应用程序文件,负责初始化gin上下文,处理信号量
package app import ( "context" "log" "net/http" "os" "os/signal" "time" "github.com/gin-gonic/gin" ) type Config struct { Port string Debug bool } func Run(cfg Config) { router := gin.Default() srv := &http.Server{ Addr: ":" + cfg.Port, Handler: router, } go func() { if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("listen: %s\n", err) } }() quit := make(chan os.Signal) signal.Notify(quit, os.Interrupt) <-quit log.Println("Shutdown Server ...") ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatal("Server Shutdown:", err) } }
2) controllers/user.go 控制文件,获取请求参数,调用service的逻辑方法,然后结果
package controllers import ( "net/http" "web_api/service" "github.com/gin-gonic/gin" ) func GetUserName(c *gin.Context) { id := c.Param("id") r := service.User{ID: id} u, err := r.GetName() if nil != err { c.String(http.StatusInternalServerError, err.Error()) return } c.JSON(http.StatusOK, u) }
3) models/model.go 数据库的初始化
package models import ( "fmt" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" ) // Config 配置 type Config struct { User string Password string Host string Name string } var ( db *gorm.DB ) // Setup initializes the database instance func Setup(cfg Config) error { var err error db, err = gorm.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local", cfg.User, cfg.Password, cfg.Host, cfg.Name)) if err != nil { return err } db.SingularTable(true) db.DB().SetMaxIdleConns(56) db.DB().SetMaxOpenConns(128) return nil } // CloseDB closes database connection (unnecessary) func CloseDB() { defer db.Close() }
4) models/user.go user数据库表的增删改查
package models import ( "github.com/jinzhu/gorm" ) type User struct { ID string `gorm:"primary_key;type:INT(20)"` Age int32 `gorm:"type:INT(20)"` Name string `gorm:"type:VARCHAR(256)"` Desc string `gorm:"type:VARCHAR(256)"` } func GetUser(id string) (*User, error) { u := &User{ ID: id, } err := db.First(u).Error if err != nil && err != gorm.ErrRecordNotFound { return nil, err } return u, nil }
5) routers/router.go 定义路由
package routers import ( "web_api/controllers" "github.com/gin-gonic/gin" ) // RegisterRouters ... func RegisterRouters(g *gin.Engine) { api := g.Group("/api") v1 := api.Group("/v1") { v1.GET("/name/:id", controllers.GetName) } }
6) server/user.go user的逻辑
package service import ( "web_api/models" ) type User struct { ID string } func (r *User) GetName() (string, error) { u, err := models.GetUser(r.ID) if nil != err { return "", err } return u.Name, nil }
7) main.go
package main import ( "flag" "io/ioutil" "log" "web_api/app" "web_api/models" "gopkg.in/yaml.v2" ) // Config 配置 type Config struct { App app.Config Model models.Config } var ( cfgPath = flag.String("config", "config.yml", "config file path") ) func main() { cfg := Config{} if data, err := ioutil.ReadFile(*cfgPath); nil != err { panic(err) } else { if err := yaml.Unmarshal(data, &cfg); nil != err { panic(err) } } if err := models.Setup(cfg.Model); nil != err { panic(err) } app.Run(cfg.App) log.Println("Server exiting") }
3.配置文件 confg.yml
app: port: 8080 debug: true model: user: root password: xxxxx host: 127.0.0.1:3306 name: mydb
4 说明
1)这是一个简单MVC结构,当然也可以不套用。这种结构用来开发web程序结构会清晰很多。
2)使用了go modules的包管理方式确实方便很多。不清楚的可以看我另外一篇关于go modules的介绍https://www.cnblogs.com/mrblue/p/11277100.html
3)依赖了yml和gorm库