[Golang] Gin框架学习笔记
0x0 Gin简介
1.Gin 是什么?
Gin 是一个用 Go (Golang) 编写的 HTTP web 框架。 它是一个类似于 martini 但拥有更好性能的 API 框架, 由于 httprouter,速度提高了近 40 倍。如果你需要极好的性能,使用 Gin 吧。
2.Gin相关地址
doc:https://gin-gonic.com/zh-cn/docs/
github:https://github.com/gin-gonic/gin
0x1 快速开始
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/ping
0x2 实践
1. 说明
1)这是一个简单的例子,实现了通过id查找数据库获取用户名字的功能。
2)使用了MVC结构,当然也可以不套用这种结构。好处就是开发web程序结构会清晰很多。
3)使用了go modules的包管理方式确实方便很多。不清楚的可以看我另外一篇关于go modules的介绍https://www.cnblogs.com/mrblue/p/11277100.html
4)依赖了yml和gorm库
2.目录结构如下
│ 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
│
├─routers
│ router.go
│
└─service
user.go
3.主要文件说明
1)app/app.go 应用程序文件,负责初始化gin上下文,处理信号量
package app import ( "context" "log" "net/http" "os" "os/signal" "time" "web_api/routers" "github.com/gin-gonic/gin" ) type Config struct { Port string Debug bool } func Run(cfg Config) { router := gin.Default() routes.RegisterRouters(router) 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 GetName(c *gin.Context) { id := c.Param("id") r := service.User{ID: id} name, err := r.GetName() if nil != err { c.String(http.StatusInternalServerError, err.Error()) return } c.JSON(http.StatusOK, gin.H{"error": "ok", "name": name}) }
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 (User) TableName() string {
return "user"
}
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) { g.GET("/name/:id", controllers.GetName) }
6) service/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") }
4.配置文件 confg.yml
app: port: 8080 debug: true model: user: root password: xxxxx host: 127.0.0.1:3306 name: mydb
5.测试
1)需要你的mysql有个叫mydb的库,里有一张叫user的表
2)查找id魏1000的人的名字,浏览器打开 http://127.0.0.1:8080/name/1000