[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

posted @ 2019-08-30 14:37  MrBlue  阅读(2659)  评论(0编辑  收藏  举报