// 使用本地module
go mod edit -require=local.com/sai0556/gin-frame@v1.0.0
go mod edit -replace=local.com/sai0556/gin-frame@v1.0.0=$PWD

編碼

配置部分

新建config目錄,初始化并監聽文件:

go

package config

import (
"fmt"

"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
)

type Config struct {
Name string
}

// 初始化配置
func Init(cfg string) error {
c := Config{
Name: cfg,
}

if err := c.initConfig(); err != nil {
return err
}

c.watchConfig()

return nil
}

func (c *Config) initConfig() error {
if c.Name != "" {
viper.SetConfigFile(c.Name)
} else {
// 默認配置文件是conf/config.yaml
viper.AddConfigPath("conf")
viper.SetConfigName("config")
}

viper.SetConfigType("yaml")
// viper解析配置文件
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
fmt.Println(viper.GetString("name"))

return nil
}

func (c *Config) watchConfig() {
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
})
}

conf/config.yaml,語法可自行研究下,比較簡單。
YAML入門

code

name: gin-frame
db:
name: blog
host: 127.0.0.1:3306
username: root
password: 111111
charset: utf8mb4

數據庫gorm

連接數據庫,構建連接池:

go

package model

import (
"fmt"
"sync"
"errors"

orm "github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"github.com/spf13/viper"
)

type MySqlPool struct {}

var instance *MySqlPool
var once sync.Once

var db *orm.DB
var err error

// 單例模式
func GetInstance() *MySqlPool {
once.Do(func() {
instance = &MySqlPool{}
})

return instance
}

func (pool *MySqlPool) InitPool() (isSuc bool) {
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=%s", viper.GetString("db.username"), viper.GetString("db.password"), viper.GetString("db.host"), viper.GetString("db.name"), viper.GetString("db.charset"))
db, err = orm.Open("mysql", dsn)
if err != nil {
panic(errors.New("mysql連接失敗"))
return false
}

// 連接數配置也可以寫入配置,在此讀取
db.DB().SetMaxIdleConns(50)
db.DB().SetMaxOpenConns(50)
// db.LogMode(true)
return true
}

main.go

我們完善一下main.go,初始化配置,并構建連接池:

go

package main
// import 這里我習慣把官方庫,開源庫,本地module依次列出
import (
"log"
"os"
"errors"

"github.com/spf13/pflag"

"local.com/sai0556/gin-frame/config"
"local.com/sai0556/gin-frame/model"
)

var (
conf = pflag.StringP("config", "c", "", "config filepath")
)

func main() {
pflag.Parse()

// 初始化配置
if err := config.Init(*conf); err != nil {
panic(err)
}

// 連接mysql數據庫
isSuc := model.GetInstance().InitPool()
if !isSuc {
log.Println("init database pool failure...")
panic(errors.New("init database pool failure"))
}
}


寫完不妨運行一下,看看效果吧!

code

go run main.go -c=./conf/config.yaml

中篇


在上篇里,我介紹了讀取配置,并嘗試連接了數據庫,那么這一篇呢,我們主要利用gin框架來寫寫簡單的接口。


路由

為了便于管理,還是將路由文件單獨出來,新建routes:

go

package router

import (
"net/http"

"github.com/gin-gonic/gin"

"local.com/sai0556/gin-frame/controller"
)

func Load(g *gin.Engine) *gin.Engine {
g.Use(gin.Recovery())
// 404
g.NoRoute(func (c *gin.Context) {
c.String(http.StatusNotFound, "404 not found");
})

g.GET("/", controller.Index)

return g
}

控制器

上面的代碼中我們看到了controller,我們建一個目錄controller:

先建base.go文件,用于寫一些基礎的方法,如SendResponse返回json。

go

package controller

import (
"net/http"

"github.com/gin-gonic/gin"
)

type Response struct {
Code int json:"code" Message string json:"message" Data interface{} json:"data" } func SendResponse(c *gin.Context, code int, message string, data interface{}) { c.JSON(http.StatusOK, Response{ Code: code, Message: message, Data: data, }) }

再來寫個index.go,處理邏輯。

go

package controller

import (
"github.com/gin-gonic/gin"
)

func Index(c *gin.Context) {
SendResponse(c, 0, "success", nil)
}

啟動gin

go

// main.go
// 在連接數據庫后加入以下代碼

gin.SetMode("debug")
g := gin.New()
g = router.Load(g)

g.Run(":8080")

不妨啟動看看效果。

go run main.go -c=./conf/config.yaml

當然,這里的服務啟動、停止可以寫得再優雅一些。

下篇

前兩篇我們已經完成了gin+gorm部分,今天我們來補充go-Redis,并進行測試。

整合go-Redis

我們把Redis相關也放在model下面,使用的是常見的go-redis:

go

// redis.go
package model

import (
"fmt"

"github.com/spf13/viper"
"github.com/go-redis/redis"
)

var RedisClient *redis.Client

func RedisInit() {
RedisClient = redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", viper.GetString("redis.host"), viper.GetString("redis.port")),
Password: viper.GetString("redis.auth"),
DB: 0,
})

_, err := RedisClient.Ping().Result()
if err != nil {
panic("redis ping error")
}
}


然后在連接Mysql的前面加入初始化redis連接的操作即可。

go

// redis 初始化
model.RedisInit()

你可以做一些簡單操作,或者在redis.go做一些常用方法的封裝,比較簡單,就不贅述了,更多go-redis操作可見:

測試

新建測試目錄test,建立三個文件:

// index.go
package test

import (
"net/http"
"io/ioutil"
)

func Sum(a int, b int) int {
return a+b
}

func HttpIndex() []byte {
resp, err := http.Get("http://127.0.0.1:8080/")
if err != nil && resp.StatusCode != 200 {
panic(err)
}
//關閉連接
defer resp.Body.Close()
//讀取報文中所有內容
body, err := ioutil.ReadAll(resp.Body)

if err != nil {
panic(err)
}
//輸出內容
return body
// index_test.go
package test

import (
"testing"
"encoding/json"

"local.com/sai0556/gin-frame/controller"
)

func TestSum(t *testing.T) {
ret := Sum(2, 7)
if ret != 9 {
t.Error("Expected 9 ~wow~")
}
}

func TestHttpIndex(t *testing.T) {
data := HttpIndex()

target := controller.Response{}
// json轉換
if err := json.Unmarshal(data, &target); err != nil {
t.Error(target)
}

ret := controller.Response{0, "success", nil}

if target != ret {
t.Error("json error")
}
}
// index_bench_test.go
package test

import (
"testing"
)

func BenchmarkSum(b *testing.B) {
for i := 0; i < b.N; i++ {
Sum(2, 7)
}
}

func BenchmarkHttpIndex(b *testing.B) {

for i := 0; i < b.N; i++ {
HttpIndex()
}
}

私以為go的測試相比其他語言還是比較簡潔的,這里需要注意幾點:

  1. 測試文件以_test結尾
  2. 基礎測試方法名要以TEST開頭

運行起來,看一下:

對圖中做一些說明:

code

// -run="none"不執行基礎單元測試,bench指定基準測試方法
go test -v -run="none" -bench="Bench*"

// 最后一個BenchmarkHttpIndex-4后面測試結果表示
一共執行了11010次,每次執行耗時107392ns(~0.107ms)

test標準庫


結后語

文章很基礎,主要是介紹了結合了gin+gorm+go-redis,并寫了簡單的測試,是相對基礎的文章,但足以應付一些api接口了。希望對你有幫助,有問題可留言或私信。

點擊查看項目DEMO

文章轉自微信公眾號@SaiWeng

熱門推薦
一個賬號試用1000+ API
助力AI無縫鏈接物理世界 · 無需多次注冊
3000+提示詞助力AI大模型
和專業工程師共享工作效率翻倍的秘密
熱門推薦
一個賬號試用1000+ API
助力AI無縫鏈接物理世界 · 無需多次注冊
返回頂部
上一篇
使用gin搭建api后臺系統之中間件開發
下一篇
Golang | Web開發之Gin使用swag生成項目的Swagger API接口文檔
国内精品久久久久影院日本,日本中文字幕视频,99久久精品99999久久,又粗又大又黄又硬又爽毛片
日韩精品一区二区三区中文不卡 | 国产电影一区在线| 99久久精品免费看| 日韩欧美专区在线| 久久九九99视频| 国产精品久久午夜| 日韩欧美中文字幕制服| 国产女人aaa级久久久级| 国产亚洲欧美一级| 免费成人在线观看| 成人app下载| 99久久99久久精品免费观看 | 日韩三级视频在线看| 国产精品久久久久久亚洲伦| 国产一区二区导航在线播放| 国产精品中文有码| 91年精品国产| 免费久久精品视频| 国产精品99久久久久久有的能看 | 国产原创一区二区三区| 7777精品伊人久久久大香线蕉超级流畅 | 色狠狠色噜噜噜综合网| 亚洲午夜精品17c| 精品无人码麻豆乱码1区2区 | 国产精品一级在线| 精品久久久影院| 亚洲免费在线看| 日本女优在线视频一区二区| 欧洲色大大久久| 精品一区二区三区不卡| 91精品婷婷国产综合久久性色 | 欧美日韩免费一区二区三区视频| 99久免费精品视频在线观看| 亚洲精品一二三区| 欧美精品日日鲁夜夜添| 日韩国产精品久久| 日韩美女精品在线| 婷婷久久综合九色综合绿巨人| 午夜视频一区在线观看| 夜夜嗨av一区二区三区四季av| 欧美日韩国产精品自在自线| 99re这里只有精品视频首页| 懂色av中文字幕一区二区三区| 国产91高潮流白浆在线麻豆| av一二三不卡影片| 久久成人免费日本黄色| 成人国产精品视频| 99国产精品久久久久久久久久 | 亚洲国产日韩综合久久精品| 678五月天丁香亚洲综合网| 日韩免费一区二区| 欧美日韩国产123区| 欧美性xxxxx极品少妇| 99久久精品免费| 欧美一区二区三区人| 亚洲欧美日韩精品久久久久| 成人午夜av影视| 日韩欧美国产午夜精品| 中文一区二区完整视频在线观看| 免费精品99久久国产综合精品| 久久久久久久国产精品影院| 成人高清av在线| 亚洲色图欧美在线| 欧美一级xxx| 色婷婷久久综合| 亚洲一区国产视频| 中文字幕中文字幕在线一区| 欧美最猛性xxxxx直播| 国产成人综合精品三级| 中文字幕在线一区二区三区| 91在线一区二区三区| 自拍偷拍欧美激情| 色女孩综合影院| 精品午夜久久福利影院| 亚洲欧美色一区| 久久婷婷久久一区二区三区| 亚洲伦在线观看| 色综合天天综合狠狠| 亚洲一区二区三区不卡国产欧美| 欧美日韩精品免费观看视频| 韩国视频一区二区| 美日韩一级片在线观看| 一区二区三区精密机械公司| 欧美日韩国产综合久久| 天堂蜜桃一区二区三区| 国产精品福利一区二区| 日韩免费观看2025年上映的电影| 成人激情免费视频| 国产成人免费9x9x人网站视频| 美女被吸乳得到大胸91| 美女尤物国产一区| 欧美国产视频在线| 一本高清dvd不卡在线观看| 久久综合av免费| 国产成人精品亚洲777人妖| 久久久久国产成人精品亚洲午夜| 麻豆精品久久精品色综合| 欧美裸体一区二区三区| 69成人精品免费视频| 4438x成人网最大色成网站| 欧美放荡的少妇| 午夜精品久久久久久久久久| 久久日韩粉嫩一区二区三区| 亚洲va欧美va天堂v国产综合| 婷婷丁香激情综合| av电影天堂一区二区在线观看| 欧美日韩高清不卡| 亚洲精品中文在线影院| 亚洲精品日产精品乱码不卡| 艳妇臀荡乳欲伦亚洲一区| 国产精品资源站在线| 91精品久久久久久蜜臀| 亚洲综合免费观看高清完整版在线 | 日本中文在线一区| 91污在线观看| 婷婷综合另类小说色区| 在线精品视频免费观看| 精品视频在线免费看| 亚洲色图.com| 91精品在线免费| 久久99热狠狠色一区二区| 国产日韩亚洲欧美综合| 国产高清成人在线| 日韩一区二区三区免费观看| 粉嫩高潮美女一区二区三区 | 一本大道综合伊人精品热热| 亚洲国产成人av网| 欧美激情综合五月色丁香小说| 在线免费不卡电影| 国产毛片精品国产一区二区三区| 国产精品国产三级国产aⅴ无密码| 日韩中文字幕亚洲一区二区va在线| 91理论电影在线观看| 国产精品亚洲一区二区三区妖精| 午夜激情一区二区| 亚洲影视在线观看| 亚洲柠檬福利资源导航| 国产精品久久久久久久久久免费看| 精品精品国产高清a毛片牛牛| 99re免费视频精品全部| 91小视频在线观看| 欧美做爰猛烈大尺度电影无法无天| 国产不卡视频一区| 国产精品一区二区三区网站| 丁香婷婷深情五月亚洲| 色婷婷综合视频在线观看| 91猫先生在线| 色伊人久久综合中文字幕| 欧美日韩国产一级片| 欧美日韩成人综合| 精品久久久久一区二区国产| 精品国产精品网麻豆系列| 国产视频一区二区在线观看| 国产精品美女久久久久久久| 亚洲欧美一区二区三区久本道91 | 日韩三级伦理片妻子的秘密按摩| 欧美一二三区在线| 成人免费一区二区三区在线观看| 午夜亚洲国产au精品一区二区| 视频在线观看91| 国产成人在线视频免费播放| 欧洲精品中文字幕| 成人欧美一区二区三区视频网页| 日韩经典一区二区| 欧美午夜一区二区| 久久久www成人免费毛片麻豆 | 偷拍自拍另类欧美| 色八戒一区二区三区| 国产日韩欧美精品在线| 视频一区在线播放| 8v天堂国产在线一区二区| 精品少妇一区二区三区在线视频 | 制服.丝袜.亚洲.另类.中文 | 在线亚洲一区二区| 蜜臀av性久久久久蜜臀aⅴ流畅 | 在线观看欧美日本| 久久激情综合网| 亚洲一区视频在线| 日韩三级.com| 国产性做久久久久久| 在线播放日韩导航| 国产九色精品成人porny| 国产精品三级在线观看| 欧美精品v国产精品v日韩精品| 国产福利一区二区三区视频 | 香蕉成人伊视频在线观看| 欧美成人免费网站| 日韩一级免费一区| 欧美日韩免费在线视频| 91亚洲国产成人精品一区二区三| 麻豆成人久久精品二区三区红 | 日韩一本二本av| 亚洲色图20p| 欧美成人午夜电影| 欧美亚洲一区三区| 欧美日韩免费观看一区三区| 蜜桃久久久久久久| 成人激情开心网| 欧美三区在线视频| 欧美亚洲自拍偷拍|