[Golang] gin框架学习笔记

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库

猜你喜欢

转载自www.cnblogs.com/mrblue/p/11434895.html