zoukankan      html  css  js  c++  java
  • [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
    ", 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

  • 相关阅读:
    面向对象介绍
    常用模块2
    常用模块1
    常用模块3
    模块导入以及常用模块
    模块介绍
    Astra: Apache Cassandra的未来是云原生
    麦格理银行借助DataStax Enterprise (DSE) 驱动数字化转型
    Apache Cassandra使用报告2020
    比较Apache Cassandra的压力测试工具
  • 原文地址:https://www.cnblogs.com/mrblue/p/11434895.html
Copyright © 2011-2022 走看看