[Golang] Gin框架學習筆記

 

0x0 Gin簡介

1.Gin 是什麼?

Gin 是一個用 Go (Golang) 編寫的 HTTP web 框架。 它是一個相似於 martini 但擁有更好性能的 API 框架, 因爲 httprouter,速度提升了近 40 倍。若是你須要極好的性能,使用 Gin 吧。html

2.Gin相關地址

doc:https://gin-gonic.com/zh-cn/docs/mysql

github:https://github.com/gin-gonic/gingit

 

0x1 快速開始

1. 用module模式建立工程

mkdir web_apigithub

cd web_apiweb

go mod init web_apisql

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查找數據庫獲取用戶名字的功能。api

2)使用了MVC結構,固然也能夠不套用這種結構。好處就是開發web程序結構會清晰不少。瀏覽器

3)使用了go modules的包管理方式確實方便不少。不清楚的能夠看我另一篇關於go modules的介紹http://www.javashuo.com/article/p-pmgommae-kp.htmlapp

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

相關文章
相關標籤/搜索