欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

加速開(kāi)發(fā):使用Go語(yǔ)言和Gin框架構(gòu)建Web項(xiàng)目的利器

 更新時(shí)間:2023年09月25日 08:38:17   作者:青絲南開(kāi)  
Go語(yǔ)言和Gin框架是構(gòu)建高性能Web項(xiàng)目的利器,Go語(yǔ)言的簡(jiǎn)潔性和并發(fā)性,以及Gin框架的輕量級(jí)和快速路由能力,使開(kāi)發(fā)者能夠快速構(gòu)建可靠的Web應(yīng)用程序,需要的朋友可以參考下

節(jié)省時(shí)間與精力,更高效地打造穩(wěn)定可靠的Web項(xiàng)目:基于Go語(yǔ)言和Gin框架的完善Web項(xiàng)目骨架。無(wú)需從零開(kāi)始,直接利用這個(gè)骨架,快速搭建一個(gè)功能齊全、性能優(yōu)異的Web應(yīng)用。充分發(fā)揮Go語(yǔ)言和Gin框架的優(yōu)勢(shì),輕松處理高并發(fā)、大流量的請(qǐng)求。構(gòu)建可擴(kuò)展性強(qiáng)、易于維護(hù)的代碼架構(gòu),保證項(xiàng)目的長(zhǎng)期穩(wěn)定運(yùn)行。同時(shí),通過(guò)集成常用功能模塊和最佳實(shí)踐,減少繁瑣的開(kāi)發(fā)工作,使您專(zhuān)注于業(yè)務(wù)邏輯的實(shí)現(xiàn)。

該骨架每個(gè)組件之間可單獨(dú)使用,組件之間松耦合,高內(nèi)聚,組件的實(shí)現(xiàn)基于其他三方依賴(lài)包的封裝。
目前該骨架實(shí)現(xiàn)了大多數(shù)的組件,比如事件,中間件,日志,配置,參數(shù)驗(yàn)證,命令行,定時(shí)任務(wù)等功能,目前可以滿(mǎn)足大多數(shù)開(kāi)發(fā)需求,后續(xù)會(huì)持續(xù)維護(hù)更新功能。

github地址:https://github.com/czx-lab/skeleton

設(shè)置環(huán)境變量并下載項(xiàng)目依賴(lài)

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
go mod download

運(yùn)行項(xiàng)目

go run ./cmd/main.go

項(xiàng)目編譯打包運(yùn)行

go build ./cmd/main.go
// 編譯
make build
// 運(yùn)行
make run
// 編譯與運(yùn)行
make
// 運(yùn)行項(xiàng)目
./main

項(xiàng)目目錄結(jié)構(gòu)說(shuō)明

├─app
│  ├─command ---> 命令行
│  ├─controller
│  │    └─base.go ---> BaseController,主要定義了request參數(shù)驗(yàn)證器validator
│  ├─event
│  │  ├─entity ---> 事件實(shí)體目錄
│  │  ├─listen ---> 事件監(jiān)聽(tīng)執(zhí)行腳本目錄
│  │  └─event.go ---> 事件注冊(cè)代碼
│  │       
│  ├─middleware ---> 中間件代碼目錄
│  ├─request ---> 請(qǐng)求參數(shù)校驗(yàn)代碼目錄
│  │   └─request.go ---> 參數(shù)驗(yàn)證器
│  └─task ---> 定時(shí)任務(wù)代碼目錄
│     └─task.go ---> 注冊(cè)定時(shí)任務(wù)腳本
├─cmd ---> 項(xiàng)目入口目錄
│  └─cli ---> 項(xiàng)目命令行模式入口目錄
├─config
│  └─config.yaml ---> 配置文件
├─internal ---> 包含第三方包的封裝
├─router ---> 路由目錄
│  └─router.go
├─storage ---> 日志、資源存儲(chǔ)目錄
│  └─logs
└─test ---> 單元測(cè)試目錄

基礎(chǔ)功能

路由

該骨架的web框架是gin,所以路由定義可直接閱讀Gin框架的文檔。

在該骨架中定義注冊(cè)路由需要在router文件夾下面的router.go文件中的func (*AppRouter) Add(server *gin.Engine)方法定義注冊(cè):

server.GET("/foo", func(ctx *gin.Context) {
    ctx.String(http.StatusOK, "hello word!")
})

也可以通過(guò)自己定義路由的定義注冊(cè),只需要實(shí)現(xiàn)github.com/czx-lab/skeleton/internal/server/router下面的Interface接口。如下示例:
在router目錄下定義了一個(gè)CustomRouter結(jié)構(gòu)體,該結(jié)構(gòu)體實(shí)現(xiàn)了Interface接口

package router
import (
    "net/http"
    "skeleton/internal/server"
    "github.com/gin-gonic/gin"
)
type CustomRouter struct {
    server server.HttpServer
}
func NewCustom(srv server.HttpServer) *CustomRouter {
    return &CustomRouter{
        srv,
    }
}
func (*CustomRouter) Add(srv *gin.Engine) {
    srv.GET("/custom", func(ctx *gin.Context) {
        ctx.String(http.StatusOK, "custom router")
    })
}

需要注意的是,如果是自定義路由注冊(cè),需要修改項(xiàng)目cmd文件夾下面的main.go入口文件,通過(guò)http.SetRouters(router.NewCustom(http))注冊(cè)給gin

中間件

定義中間件與gin框架一樣,該估計(jì)默認(rèn)實(shí)現(xiàn)了panic異常的中間件,可以查看internal/server/middleware文件夾中的exception.go文件。

如果需要定義其他的中間件并加載注冊(cè),可以將定義好的中間件通過(guò)server.HttpServer接口的SetMiddleware(middlewares ...middleware.Interface)方法注冊(cè)加載,
比如我們實(shí)現(xiàn)如下自定義全局中間件middleware/custom.go

type Custom struct{}
func (c *Custom) Handle() gin.HandlerFunc {
    return func(ctx *gin.Context) {
        fmt.Println("Custom middleware exec...")
    }
}

然后在定義路由的地方使用server.SetMiddleware(&middleware.Custom{})注冊(cè)中間件。
定義全局路由中間件可以參考router/router.go中的New方法。

如果是局部中間件,可以直接在具體的路由上注冊(cè),參考gin路由中間件的用法

日志

在該骨架中的日志是直接對(duì)go.uber.org/zap的封裝,使用時(shí),直接通過(guò)全局變量variable.Log訪問(wèn)寫(xiě)入日志,可直接使用zap支持的所有方法。

package demo
import "skeleton/internal/variable"
func Demo() {
    variable.Log.Info("info message")
}

日志文件默認(rèn)是以json格式寫(xiě)入到storage/logs/system.log里面

配置

配置項(xiàng)的定義直接在config/config.yaml文件中定義,并且配置的讀取寫(xiě)入是通過(guò)封裝github.com/spf13/viper實(shí)現(xiàn),在該骨架中,只提供了如下一些獲取配置的方法:

type ConfigInterface interface {
	Get(key string) any
	GetString(key string) string
	GetBool(key string) bool
	GetInt(key string) int
	GetInt32(key string) int32
	GetInt64(key string) int64
	GetFloat64(key string) float64
	GetDuration(key string) time.Duration
	GetStringSlice(key string) []string
}

需要注意的是,骨架中對(duì)配置項(xiàng)的獲取做了緩存的處理,第一次加載是在文件中獲取,后面每次回去都是在cache中獲取,目前cache默認(rèn)只支持memory,骨架中也支持自定義cache的方法,只需要實(shí)現(xiàn)config.CacheInterface接口就可以,比如需要使用redis作為配置緩存,可以通過(guò)下面的方式處理:

type ConfigRedisCache struct {}
var _ config.CacheInterface = (*ConfigRedisCache)(nil)
func (c *ConfigRedisCache) Get(key string) any {
    return nil
}
func (c *ConfigRedisCache) Set(key string, value any) bool {
    return true
}
func (c *ConfigRedisCache) Has(key string) bool {
    return true
}
func (c *ConfigRedisCache) FuzzyDelete(key string) {
}

然后將ConfigRedisCache結(jié)構(gòu)體配置到config.Options中,如下所示,修改internal/bootstrap/init.go初始化配置的方法:

variable.Config, err := config.New(driver.New(), config.Options{
	BasePath: './',
    Cache: &ConfigRedisCache{}
})

config.yaml基礎(chǔ)配置如下:

# http配置
HttpServer:
  Port: ":8888"
  # 服務(wù)模式,和gin的gin.SetMode的值是一樣的
  Mode: "debug"
# socket配置
Websocket:
  WriteReadBufferSize: 2048
  HeartbeatFailMaxTimes: 4
  PingPeriod: 20
  ReadDeadline: 100
  WriteDeadline: 35
  PingMsg: "ping"
# 數(shù)據(jù)庫(kù)配置
Database:
  # 可以查看GORM相關(guān)的配置選項(xiàng)
  Mysql:
    SlowThreshold: 5
    LogLevel: 4
    ConnMaxLifetime: 1
    MaxIdleConn: 2
    MaxOpenConn: 2
    ConnMaxIdleTime: 12
    Reade:
      - "root:root@tcp(192.168.1.4:3306)/test?charset=utf8mb4&loc=Local&parseTime=True"
    Write: "root:root@tcp(192.168.1.4:3306)/test?charset=utf8mb4&loc=Local&parseTime=True"
  # mongo數(shù)據(jù)庫(kù)的基礎(chǔ)配置
  Mongo:
    Enable: false
    Uri:
    MinPoolSize: 10
    MaxPoolSize: 20
Redis:
  Disabled: false
  Addr: "192.168.1.4:6379"
  Pwd: ""
  Db: 0
  PoolSize: 20
  MaxIdleConn: 30
  MinIdleConn: 10
  # 單位(秒)
  MaxLifeTime: 60
  # 單位(分)
  MaxIdleTime: 30
# 定時(shí)任務(wù)
Crontab:
  Enable: true
# 消息隊(duì)列,使用rocketmq
MQ:
  Enable: false
  Servers:
    - "127.0.0.1:9876"
  ConsumptionSize: 1
  Retries: 1

事件機(jī)制

  • 定義事件實(shí)體

    app/event/entity目錄下定義一個(gè)事件實(shí)體,該實(shí)體實(shí)現(xiàn)了event.EventInterface接口:

    package entity
    type DemoEvent struct {}
    func (d *DemoEvent) EventName() string {
        return "demo-event"
    }
    func (d *DemoEvent) GetData() any {
        return "demo param"
    }
  • 定義事件監(jiān)聽(tīng)

    app/event/listen目錄中定義一個(gè)DemoEventListen事件監(jiān)聽(tīng),并且該DemoEventListen結(jié)構(gòu)體必須要實(shí)現(xiàn)event.Interface接口:

    package listen
    import (
    	"fmt"
    	event2 "skeleton/app/event/entity"
    	"skeleton/internal/event"
    )
    type DemoEventListen struct {
    }
    func (*DemoEventListen) Listen() event.EventInterface {
    	return &event2.DemoEvent{}
    }
    func (*DemoEventListen) Process(data any) (any, error) {
    	return fmt.Sprintf("%v --> %s", data, "exec DemoEventListen.Process"), nil
    }
  • 最后需要將事件進(jìn)行注冊(cè),在app/event/event.go文件中的Init方法內(nèi)執(zhí)行:

    variable.Event.Register(&listen.DemoEventListen{})
  • 調(diào)用事件執(zhí)行

    variable.Event.Dispatch(&entity.DemoEvent{})

驗(yàn)證器

gin框架本身內(nèi)置了validator校驗(yàn),骨架里面只是對(duì)其參數(shù)的校驗(yàn)做了統(tǒng)一的校驗(yàn)入口。

通過(guò)如下方式獲取進(jìn)行參數(shù)的校驗(yàn),并設(shè)置中文錯(cuò)誤提示:

type Param struct {
    Name  int    `binding:"required" form:"name" query:"name" json:"name"`
}
appRequest, err := AppRequest.New("zh")
if err != nil {
    return
}
var data Param
errMap := appRequest.Validator(ctx, &data)
fmt.Println(errMap)

骨架里面已經(jīng)實(shí)現(xiàn)了默認(rèn)的參數(shù)校驗(yàn),可以在app/request/request.go文件中查看。并且在controller目錄中base.go有一個(gè)Validate(ctx *gin.Context, param any)方法,在其他controller中要進(jìn)行參數(shù)校驗(yàn)的時(shí)候,只需要繼承base結(jié)構(gòu)體,然后調(diào)用Validate方法。

package controller
import "github.com/gin-gonic/gin"
type DemoController struct {
    base
}
type DemoRequest struct {
    Id int `binding:"required" form:"id" query:"id" json:"id"`
}
func (d *DemoController) Index(ctx *gin.Context) {
    var param DemoRequest
    if err := d.base.Validate(ctx, &param); err == nil {
		ctx.JSON(http.StatusOK, gin.H{"data": param})
	} else {
		ctx.JSON(http.StatusBadRequest, gin.H{"message": err})
	}
}

驗(yàn)證規(guī)格參考github.com/go-playground/validator官方文檔

命令行

基于github.com/spf13/cobra封裝

  • 定義命令

    app/command目錄中定義自己的命令,比如自定義一個(gè)輸出success ok的命令

    package command
    import (
        "fmt"
        "github.com/spf13/cobra"
    )
    type FooCommand struct {}
    func (f *FooCommand) Command() *cobra.Command {
        return &cobra.Command{
    		Use:   "foo",
    		Short: "命令使用簡(jiǎn)介.",
    		Long: `命令介紹.`,
    		Run: func(cmd *cobra.Command, args []string) {
    			str, _ := cmd.Flags().GetString("name")
                 fmt.Printf("success, %s", str)
    		},
    	}
    }
    func (f *FooCommand) Flags(root *cobra.Command) {
    	root.PersistentFlags().String("name", "", "命令參數(shù)")
    }
  • 注冊(cè)命令

    需要在cmd/cli/cli.go中的main方法內(nèi)注冊(cè)自定義命令。

  • 執(zhí)行命令

    go run cmd/cli/cli.go foo --name ok
  • 查看命令信息

    go run cmd/cli/cli.go help
    // 或者
    go run cmd/cli/cli.go foo --help

定時(shí)任務(wù)

定時(shí)是通過(guò)封裝github.com/robfig/cron/v3實(shí)現(xiàn)

  • 定義定時(shí)任務(wù)方法

    app/task目錄下定義執(zhí)行方法,比如每一分鐘打印success字符

    package task
    import "fmt"
    type SuccessTask struct {
    }
    // 時(shí)間規(guī)則
    func (s *SuccessTask) Rule() string {
    	return "* * * * *"
    }
    func (s *SuccessTask) Execute() func() {
    	return func() {
    		fmt.Println("success")
    	}
    }
  • 加載定時(shí)任務(wù)

    需要在app/task/task.go文件中的Tasks方法內(nèi),加載自定義的任務(wù),參考task目錄下的task.go文件

Go語(yǔ)言和Gin框架是開(kāi)發(fā)高性能Web項(xiàng)目的理想選擇。Go語(yǔ)言以其簡(jiǎn)潔性、高效性和并發(fā)性而聞名,使開(kāi)發(fā)者能夠編寫(xiě)可靠且高性能的代碼。而Gin框架是一個(gè)輕量級(jí)的Web框架,具有快速的路由能力和豐富的中間件支持,使開(kāi)發(fā)者能夠快速構(gòu)建靈活且可擴(kuò)展的Web應(yīng)用程序。使用Go語(yǔ)言和Gin框架,開(kāi)發(fā)者可以享受到高效的開(kāi)發(fā)過(guò)程和出色的性能表現(xiàn)。無(wú)論是構(gòu)建小型項(xiàng)目還是大型應(yīng)用程序,Go語(yǔ)言和Gin框架都能為開(kāi)發(fā)者提供強(qiáng)大的工具和優(yōu)化的性能,使開(kāi)發(fā)過(guò)程更加高效和愉快。

到此這篇關(guān)于加速開(kāi)發(fā):使用Go語(yǔ)言和Gin框架構(gòu)建Web項(xiàng)目的利器的文章就介紹到這了,更多相關(guān)基于go語(yǔ)言gin框架的web項(xiàng)目骨架 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang中runtime的使用詳解

    Golang中runtime的使用詳解

    這篇文章主要介紹了Golang中runtime的使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Go計(jì)算某段代碼運(yùn)行所耗時(shí)間簡(jiǎn)單實(shí)例

    Go計(jì)算某段代碼運(yùn)行所耗時(shí)間簡(jiǎn)單實(shí)例

    這篇文章主要給大家介紹了關(guān)于Go計(jì)算某段代碼運(yùn)行所耗時(shí)間的相關(guān)資料,主要介紹了Golang記錄計(jì)算函數(shù)執(zhí)行耗時(shí)、運(yùn)行時(shí)間的一個(gè)簡(jiǎn)單方法,文中給出了詳細(xì)的代碼示例,需要的朋友可以參考下
    2023-11-11
  • golang類(lèi)型轉(zhuǎn)換之interface轉(zhuǎn)字符串string簡(jiǎn)單示例

    golang類(lèi)型轉(zhuǎn)換之interface轉(zhuǎn)字符串string簡(jiǎn)單示例

    在我們使用Golang進(jìn)行開(kāi)發(fā)過(guò)程中,總是繞不開(kāi)對(duì)字符或字符串的處理,這篇文章主要給大家介紹了關(guān)于golang類(lèi)型轉(zhuǎn)換之interface轉(zhuǎn)字符串string的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • Golang實(shí)現(xiàn)優(yōu)雅的將struct轉(zhuǎn)換為map

    Golang實(shí)現(xiàn)優(yōu)雅的將struct轉(zhuǎn)換為map

    在項(xiàng)目實(shí)踐中,有時(shí)候我們需要將struct結(jié)構(gòu)體轉(zhuǎn)為map映射表,然后基于map做數(shù)據(jù)裁剪或操作。那么下面我來(lái)介紹下常用的兩種轉(zhuǎn)換方式,希望對(duì)大家有所幫助
    2023-01-01
  • GoLang并發(fā)機(jī)制探究goroutine原理詳細(xì)講解

    GoLang并發(fā)機(jī)制探究goroutine原理詳細(xì)講解

    goroutine是Go語(yǔ)言提供的語(yǔ)言級(jí)別的輕量級(jí)線(xiàn)程,在我們需要使用并發(fā)時(shí),我們只需要通過(guò) go 關(guān)鍵字來(lái)開(kāi)啟 goroutine 即可。這篇文章主要介紹了GoLang并發(fā)機(jī)制goroutine原理,感興趣的可以了解一下
    2022-12-12
  • Go語(yǔ)言實(shí)現(xiàn)多協(xié)程文件下載器的過(guò)程詳解

    Go語(yǔ)言實(shí)現(xiàn)多協(xié)程文件下載器的過(guò)程詳解

    這篇文章主要介紹了Go語(yǔ)言實(shí)現(xiàn)多協(xié)程文件下載器的相關(guān)資料,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2024-08-08
  • go中sync.RWMutex的源碼解讀

    go中sync.RWMutex的源碼解讀

    本文主要介紹了go中sync.RWMutex的源碼解讀,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-04-04
  • go 讀取BMP文件頭二進(jìn)制讀取方式

    go 讀取BMP文件頭二進(jìn)制讀取方式

    這篇文章主要介紹了go 讀取BMP文件頭二進(jìn)制讀取方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • Go語(yǔ)言實(shí)現(xiàn)Snowflake雪花算法

    Go語(yǔ)言實(shí)現(xiàn)Snowflake雪花算法

    雪花算法產(chǎn)生的背景當(dāng)然是twitter高并發(fā)環(huán)境下對(duì)唯一ID生成的需求,得益于twitter內(nèi)部牛的技術(shù),雪花算法能夠流傳于至今并且被廣泛使用,本文就詳細(xì)的介紹一下,感興趣的可以了解一下
    2021-06-06
  • Go語(yǔ)言method詳解

    Go語(yǔ)言method詳解

    這篇文章主要介紹了Go語(yǔ)言method詳解,本文總結(jié)了在使用method的時(shí)候重要注意幾點(diǎn)、指針作為receiver、method繼承等內(nèi)容,需要的朋友可以參考下
    2014-10-10

最新評(píng)論