├── lib └── .gitkeep ├── pkg └── .gitkeep ├── nofx ├── lib │ └── .gitkeep ├── pkg │ └── .gitkeep ├── internal │ ├── .gitkeep │ └── database │ │ └── database.go └── cmd │ └── api │ └── main.go ├── .gitignore ├── benchmarks ├── fx-k6-100.png ├── nofx-k6-100.png ├── fx-cpu-memory-plot-20.load.png ├── fx-cpu-memory-plot-600.idle.png ├── nofx-cpu-memory-plot-20.load.png └── nofx-cpu-memory-plot-600.idle.png ├── scripts ├── load.k6.js └── psrecord.sh ├── Makefile ├── internal ├── web │ ├── webserver │ │ └── webserver.go │ ├── router │ │ └── router.go │ └── controller │ │ └── controller.go └── database │ └── database.go ├── go.mod ├── cmd └── api │ └── main.go ├── README.md └── go.sum /lib/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pkg/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nofx/lib/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nofx/pkg/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nofx/internal/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | dist 3 | 4 | -------------------------------------------------------------------------------- /benchmarks/fx-k6-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanoschrs/go-fx-test/HEAD/benchmarks/fx-k6-100.png -------------------------------------------------------------------------------- /benchmarks/nofx-k6-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanoschrs/go-fx-test/HEAD/benchmarks/nofx-k6-100.png -------------------------------------------------------------------------------- /benchmarks/fx-cpu-memory-plot-20.load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanoschrs/go-fx-test/HEAD/benchmarks/fx-cpu-memory-plot-20.load.png -------------------------------------------------------------------------------- /benchmarks/fx-cpu-memory-plot-600.idle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanoschrs/go-fx-test/HEAD/benchmarks/fx-cpu-memory-plot-600.idle.png -------------------------------------------------------------------------------- /benchmarks/nofx-cpu-memory-plot-20.load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanoschrs/go-fx-test/HEAD/benchmarks/nofx-cpu-memory-plot-20.load.png -------------------------------------------------------------------------------- /benchmarks/nofx-cpu-memory-plot-600.idle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanoschrs/go-fx-test/HEAD/benchmarks/nofx-cpu-memory-plot-600.idle.png -------------------------------------------------------------------------------- /scripts/load.k6.js: -------------------------------------------------------------------------------- 1 | import http from 'k6/http' 2 | import { sleep } from 'k6' 3 | 4 | export default function () { 5 | http.get(`http://127.0.0.1:${__ENV.PORT}/something`) 6 | sleep(.25) 7 | } 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #!make 2 | 3 | run: 4 | find . -name '*.go' 2>&1 | entr -r bash -c "go run ./cmd/api 2>&1" 5 | run-nofx: 6 | cd nofx && find . -name '*.go' 2>&1 | entr -r bash -c "go run ./cmd/api 2>&1" 7 | 8 | build: 9 | go build -trimpath -ldflags "-s -w" -o ./dist/api ./cmd/api 10 | build-nofx: 11 | cd nofx && go build -trimpath -ldflags "-s -w" -o ../dist/api-nofx ./cmd/api 12 | 13 | -------------------------------------------------------------------------------- /internal/web/webserver/webserver.go: -------------------------------------------------------------------------------- 1 | package webserver 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "go.uber.org/fx" 6 | ) 7 | 8 | type Webserver struct { 9 | Gin *gin.Engine 10 | } 11 | 12 | func New() *Webserver { 13 | g := gin.New() 14 | g.SetTrustedProxies(nil) 15 | 16 | var webserver = new(Webserver) 17 | webserver.Gin = g 18 | 19 | return webserver 20 | } 21 | 22 | var Module = fx.Options(fx.Provide(New)) 23 | -------------------------------------------------------------------------------- /internal/web/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/stefanoschrs/go-fx-test/internal/web/controller" 5 | "github.com/stefanoschrs/go-fx-test/internal/web/webserver" 6 | 7 | "go.uber.org/fx" 8 | ) 9 | 10 | func registerRoutes(webserver *webserver.Webserver, controller *controller.Controller) { 11 | webserver.Gin.GET("/ping", controller.Ping) 12 | 13 | webserver.Gin.GET("/something", controller.GetSomething) 14 | } 15 | 16 | var Module = fx.Options(fx.Invoke(registerRoutes)) 17 | -------------------------------------------------------------------------------- /scripts/psrecord.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 6 | cd "$DIR"/.. || exit 1 7 | 8 | if [ $# -lt 3 ]; then 9 | echo "Usage: $0 [duration]" 10 | exit 1 11 | fi 12 | 13 | duration=$4 14 | if [[ -z "$duration" ]]; then 15 | duration=$(( 60 * 15 )) 16 | fi 17 | 18 | echo "Recording $1 for $duration seconds" 19 | exit 20 | 21 | psrecord $1 \ 22 | --include-children \ 23 | --interval 1 \ 24 | --duration ${duration} \ 25 | --plot \ 26 | benchmarks/$2-cpu-memory-plot-${duration}.$3.png 27 | -------------------------------------------------------------------------------- /internal/web/controller/controller.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/stefanoschrs/go-fx-test/internal/database" 7 | 8 | "github.com/gin-gonic/gin" 9 | "go.uber.org/fx" 10 | "go.uber.org/zap" 11 | ) 12 | 13 | type Controller struct { 14 | logger *zap.Logger 15 | database *database.Database 16 | } 17 | 18 | func (ctrl *Controller) Ping(c *gin.Context) { 19 | ctrl.logger.Debug("Controller.Ping") 20 | 21 | c.JSON(http.StatusOK, gin.H{ 22 | "message": "pong", 23 | }) 24 | } 25 | 26 | func (ctrl *Controller) GetSomething(c *gin.Context) { 27 | ctrl.logger.Debug("Controller.GetSomething") 28 | 29 | number, err := ctrl.database.GetRandomNumber() 30 | if err != nil { 31 | ctrl.logger.Error("database.GetRandomNumber", zap.Error(err)) 32 | c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) 33 | return 34 | } 35 | 36 | c.JSON(http.StatusOK, gin.H{ 37 | "number": number, 38 | }) 39 | } 40 | 41 | func New(logger *zap.Logger, database *database.Database) *Controller { 42 | var controller = new(Controller) 43 | controller.logger = logger 44 | controller.database = database 45 | 46 | return controller 47 | } 48 | 49 | var Module = fx.Provide(New) 50 | -------------------------------------------------------------------------------- /nofx/internal/database/database.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path" 7 | 8 | "go.uber.org/zap" 9 | "gorm.io/driver/sqlite" 10 | "gorm.io/gorm" 11 | gormlogger "gorm.io/gorm/logger" 12 | "moul.io/zapgorm2" 13 | ) 14 | 15 | type Database struct { 16 | logger *zap.Logger 17 | db *gorm.DB 18 | } 19 | 20 | func (d *Database) GetRandomNumber() (number int, err error) { 21 | d.logger.Debug("Database.GetRandomNumber") 22 | 23 | var result struct { 24 | Number int 25 | } 26 | 27 | // Do some calculations to consume resources 28 | res := d.db.Raw(` 29 | WITH RECURSIVE foo(cur, nex) AS ( 30 | SELECT 1,1 31 | UNION ALL 32 | SELECT nex, cur+1 33 | FROM foo 34 | LIMIT 100000 35 | ) SELECT sum(cur) AS number 36 | FROM foo; 37 | `).Scan(&result) 38 | if res.Error != nil { 39 | err = fmt.Errorf("res.Error: %w", res.Error) 40 | return 41 | } 42 | 43 | number = result.Number 44 | return 45 | } 46 | 47 | func New(logger *zap.Logger) (database *Database, err error) { 48 | gormLogger := zapgorm2.New(logger) 49 | gormLogger.SetAsDefault() 50 | gormLogger.LogLevel = gormlogger.Warn 51 | 52 | dbPath := os.Getenv("DB_PATH") 53 | if dbPath == "" { 54 | dbPath = path.Join(os.TempDir(), "go-fx-test.db") 55 | } 56 | 57 | db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{ 58 | Logger: gormLogger, 59 | }) 60 | if err != nil { 61 | err = fmt.Errorf("gorm.Open: %w", err) 62 | return 63 | } 64 | 65 | database = new(Database) 66 | database.db = db 67 | database.logger = logger 68 | 69 | return 70 | } 71 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/stefanoschrs/go-fx-test 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.8.2 7 | github.com/go-resty/resty/v2 v2.7.0 8 | go.uber.org/fx v1.19.1 9 | go.uber.org/zap v1.23.0 10 | gorm.io/driver/sqlite v1.4.4 11 | gorm.io/gorm v1.24.3 12 | moul.io/zapgorm2 v1.2.0 13 | ) 14 | 15 | require ( 16 | github.com/gin-contrib/sse v0.1.0 // indirect 17 | github.com/go-playground/locales v0.14.0 // indirect 18 | github.com/go-playground/universal-translator v0.18.0 // indirect 19 | github.com/go-playground/validator/v10 v10.11.1 // indirect 20 | github.com/goccy/go-json v0.9.11 // indirect 21 | github.com/jinzhu/inflection v1.0.0 // indirect 22 | github.com/jinzhu/now v1.1.5 // indirect 23 | github.com/json-iterator/go v1.1.12 // indirect 24 | github.com/leodido/go-urn v1.2.1 // indirect 25 | github.com/mattn/go-isatty v0.0.16 // indirect 26 | github.com/mattn/go-sqlite3 v1.14.15 // indirect 27 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect 28 | github.com/modern-go/reflect2 v1.0.2 // indirect 29 | github.com/pelletier/go-toml/v2 v2.0.6 // indirect 30 | github.com/ugorji/go/codec v1.2.7 // indirect 31 | go.uber.org/atomic v1.7.0 // indirect 32 | go.uber.org/dig v1.16.0 // indirect 33 | go.uber.org/multierr v1.7.0 // indirect 34 | golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect 35 | golang.org/x/net v0.4.0 // indirect 36 | golang.org/x/sys v0.3.0 // indirect 37 | golang.org/x/text v0.5.0 // indirect 38 | google.golang.org/protobuf v1.28.1 // indirect 39 | gopkg.in/yaml.v2 v2.4.0 // indirect 40 | ) 41 | -------------------------------------------------------------------------------- /internal/database/database.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path" 7 | 8 | "go.uber.org/fx" 9 | "go.uber.org/zap" 10 | "gorm.io/driver/sqlite" 11 | "gorm.io/gorm" 12 | gormlogger "gorm.io/gorm/logger" 13 | "moul.io/zapgorm2" 14 | ) 15 | 16 | type Database struct { 17 | logger *zap.Logger 18 | db *gorm.DB 19 | } 20 | 21 | func (d *Database) GetRandomNumber() (number int, err error) { 22 | d.logger.Debug("Database.GetRandomNumber") 23 | 24 | var result struct { 25 | Number int 26 | } 27 | 28 | // Do some calculations to consume resources 29 | res := d.db.Raw(` 30 | WITH RECURSIVE foo(cur, nex) AS ( 31 | SELECT 1,1 32 | UNION ALL 33 | SELECT nex, cur+1 34 | FROM foo 35 | LIMIT 100000 36 | ) SELECT sum(cur) AS number 37 | FROM foo; 38 | `).Scan(&result) 39 | if res.Error != nil { 40 | err = fmt.Errorf("res.Error: %w", res.Error) 41 | return 42 | } 43 | 44 | number = result.Number 45 | return 46 | } 47 | 48 | func New(logger *zap.Logger) (database *Database, err error) { 49 | gormLogger := zapgorm2.New(logger) 50 | gormLogger.SetAsDefault() 51 | gormLogger.LogLevel = gormlogger.Warn 52 | 53 | dbPath := os.Getenv("DB_PATH") 54 | if dbPath == "" { 55 | dbPath = path.Join(os.TempDir(), "go-fx-test.db") 56 | } 57 | 58 | db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{ 59 | Logger: gormLogger, 60 | }) 61 | if err != nil { 62 | err = fmt.Errorf("gorm.Open: %w", err) 63 | return 64 | } 65 | 66 | database = new(Database) 67 | database.db = db 68 | database.logger = logger 69 | 70 | return 71 | } 72 | 73 | var Module = fx.Options(fx.Provide(New)) 74 | -------------------------------------------------------------------------------- /cmd/api/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "os" 8 | "strings" 9 | "time" 10 | 11 | "github.com/stefanoschrs/go-fx-test/internal/database" 12 | "github.com/stefanoschrs/go-fx-test/internal/web/controller" 13 | "github.com/stefanoschrs/go-fx-test/internal/web/router" 14 | "github.com/stefanoschrs/go-fx-test/internal/web/webserver" 15 | 16 | "github.com/go-resty/resty/v2" 17 | "go.uber.org/fx" 18 | "go.uber.org/fx/fxevent" 19 | "go.uber.org/zap" 20 | ) 21 | 22 | func getWebserverAddr() string { 23 | port := os.Getenv("PORT") 24 | if port == "" { 25 | port = "8080" 26 | } 27 | // e.g 127.0.0.1:8080 28 | if !strings.Contains(port, ":") { 29 | port = ":" + port 30 | } 31 | return port 32 | } 33 | 34 | func main() { 35 | fmt.Println() 36 | fmt.Println("Starting fx application...") 37 | fmt.Printf("PID: %d\n", os.Getpid()) 38 | fmt.Println() 39 | 40 | app := fx.New( 41 | webserver.Module, 42 | router.Module, 43 | controller.Module, 44 | database.Module, 45 | 46 | fx.Provide(zap.NewExample), 47 | fx.WithLogger(func(logger *zap.Logger) fxevent.Logger { 48 | return &fxevent.ZapLogger{Logger: logger} 49 | }), 50 | 51 | fx.Invoke(func(webserver *webserver.Webserver, logger *zap.Logger) { 52 | logger.Debug("Webserver module invoked") 53 | go webserver.Gin.Run(getWebserverAddr()) 54 | }, func(ctrl *controller.Controller, logger *zap.Logger) { 55 | logger.Debug("Controller module invoked") 56 | }, func(database *database.Database, logger *zap.Logger) { 57 | logger.Debug("Database module invoked") 58 | }, func(logger *zap.Logger) { 59 | logger.Debug("Logger module invoked") 60 | }), 61 | ) 62 | 63 | startCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 64 | defer cancel() 65 | if err := app.Start(startCtx); err != nil { 66 | log.Fatal(fmt.Errorf("app.Start: %w", err)) 67 | } 68 | 69 | /** 70 | * Testing if the webserver is running 71 | */ 72 | go func() { 73 | time.Sleep(5 * time.Second) 74 | 75 | res, err := resty.New().R().Get(fmt.Sprintf("http://%s/ping", getWebserverAddr())) 76 | if err != nil { 77 | log.Fatal(fmt.Errorf("resty.Get: %w", err)) 78 | } 79 | fmt.Println("Testing Server: " + string(res.Body())) 80 | }() 81 | 82 | <-app.Wait() 83 | } 84 | -------------------------------------------------------------------------------- /nofx/cmd/api/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | "os" 8 | "strings" 9 | "time" 10 | 11 | "github.com/stefanoschrs/go-fx-test/nofx/internal/database" 12 | 13 | "github.com/gin-gonic/gin" 14 | "github.com/go-resty/resty/v2" 15 | "go.uber.org/zap" 16 | ) 17 | 18 | func getWebserverAddr() string { 19 | port := os.Getenv("PORT") 20 | if port == "" { 21 | port = "8080" 22 | } 23 | // e.g 127.0.0.1:8080 24 | if !strings.Contains(port, ":") { 25 | port = ":" + port 26 | } 27 | return port 28 | } 29 | 30 | func main() { 31 | fmt.Println() 32 | fmt.Println("Starting non-fx application...") 33 | fmt.Printf("PID: %d\n", os.Getpid()) 34 | fmt.Println() 35 | 36 | /**/ 37 | // Logger 38 | /**/ 39 | 40 | logger := zap.NewExample() 41 | 42 | /**/ 43 | // Database 44 | /**/ 45 | 46 | db, err := database.New(logger) 47 | if err != nil { 48 | log.Fatal(fmt.Errorf("database.New: %w", err)) 49 | } 50 | 51 | /**/ 52 | // Webserver 53 | /**/ 54 | 55 | router := gin.New() 56 | router.SetTrustedProxies(nil) 57 | 58 | router.Use(func(c *gin.Context) { 59 | c.Set("logger", logger) 60 | c.Set("database", db) 61 | }) 62 | 63 | router.GET("/ping", func(c *gin.Context) { 64 | l := c.MustGet("logger").(*zap.Logger) 65 | l.Debug("Controller.Ping") 66 | 67 | c.JSON(http.StatusOK, gin.H{ 68 | "message": "pong", 69 | }) 70 | }) 71 | 72 | router.GET("/something", func(c *gin.Context) { 73 | l := c.MustGet("logger").(*zap.Logger) 74 | l.Debug("Controller.GetSomething") 75 | 76 | d := c.MustGet("database").(*database.Database) 77 | 78 | number, err2 := d.GetRandomNumber() 79 | if err2 != nil { 80 | l.Error("database.GetRandomNumber", zap.Error(err2)) 81 | c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err2.Error()}) 82 | return 83 | } 84 | 85 | c.JSON(http.StatusOK, gin.H{ 86 | "number": number, 87 | }) 88 | }) 89 | 90 | /** 91 | * Testing if the webserver is running 92 | */ 93 | go func() { 94 | time.Sleep(5 * time.Second) 95 | 96 | res, err := resty.New().R().Get(fmt.Sprintf("http://%s/ping", getWebserverAddr())) 97 | if err != nil { 98 | log.Fatal(fmt.Errorf("resty.Get: %w", err)) 99 | } 100 | fmt.Println("Testing Server: " + string(res.Body())) 101 | }() 102 | 103 | if err = router.Run(getWebserverAddr()); err != nil { 104 | log.Fatal(fmt.Errorf("router.Run: %w", err)) 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sample Web App 2 | 3 | > Testing Uber's fx dependency injection system for Go 4 | 5 | ## Libraries 6 | - HTTP Web Framework [Gin](https://github.com/gin-gonic/gin) 7 | - DB + ORM [GORM](https://github.com/go-gorm/gorm) 8 | - DI Framework [fx](https://github.com/uber-go/fx) 9 | - Logging [zap](https://github.com/uber-go/zap) 10 | 11 | ## Benefits 12 | 1. **Modularity and Reusability**: Fx allows you to break your application into small, independent parts that can be put together like building blocks. This makes it easy to reuse parts of the application in other projects, and to test each part separately. 13 | 2. **Explicit Dependencies**: Fx forces you to clearly define what each part of the application needs to work, making it easy to understand how everything fits together and to identify potential problems. 14 | 3. **Type Safety**: Fx uses Go's type system to make sure that each part of the application gets the right inputs, which helps prevent errors from happening at runtime. 15 | 4. **Lifecycle Management**: Fx allows you to specify what should happen when the application starts and stops, such as starting and stopping services, opening and closing connections and other tasks. 16 | 5. **Easy to Test**: Fx makes it easy to test the application by allowing you to replace parts with mock versions for testing purposes. 17 | 6. **Easy to Monitor**: Fx provides a way to monitor the status of the application and its parts, which makes it easy to identify and fix problems. 18 | 7. **Easy to extend**: Fx allows you to easily add new functionality to the framework by adding custom hooks to the application's lifecycle and by adding custom options. 19 | 20 | ## Run 21 | 22 | ```shell 23 | make run 24 | ``` 25 | 26 | ## Benchmarks 27 | 28 | - Binary size 29 | 30 | > make build 31 | 32 | | FX | No FX | 33 | | -- | -- | 34 | | 15M | 14M | 35 | | 5.9M (upx) | 5.7M (upx) | 36 | 37 | - Idle 38 | 39 | > ./scripts/psrecord.sh nofx 20 load 40 | 41 | | FX | No FX | 42 | | -- | -- | 43 | | ![](./benchmarks/fx-cpu-memory-plot-600.idle.png) | ![](./benchmarks/nofx-cpu-memory-plot-600.idle.png) | 44 | 45 | - HTTP Requests 46 | 47 | > PORT=15000 make run 48 | > psrecord --include-children --interval 1 --duration 20 --plot benchmarks/fx-cpu-memory-plot-20.load.png & k6 run --vus 100 --duration 20s -e PORT=15000 ./scripts/load.k6.js 49 | > PORT=15001 make run-nofx 50 | > psrecord --include-children --interval 1 --duration 20 --plot benchmarks/nofx-cpu-memory-plot-20.load.png & k6 run --vus 100 --duration 20s -e PORT=15001 ./scripts/load.k6.js 51 | 52 | | FX | No FX | 53 | | -- | -- | 54 | | ![](./benchmarks/fx-cpu-memory-plot-20.load.png) | ![](./benchmarks/nofx-cpu-memory-plot-20.load.png) | 55 | | ![](./benchmarks/fx-k6-100.png) | ![](./benchmarks/nofx-k6-100.png) | 56 | 57 | ## CHANGELOG 58 | ### 2023-01-21 59 | - Added database & orm with GORM 60 | - Added a non-fx version of the web app for benchmarking 61 | - Added some basic cpu/memory benchmarks 62 | - Added some basic load tests with k6 63 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 2 | github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= 3 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 4 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 6 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 8 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 9 | github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY= 10 | github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398= 11 | github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= 12 | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 13 | github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= 14 | github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= 15 | github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= 16 | github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= 17 | github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= 18 | github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= 19 | github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= 20 | github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= 21 | github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= 22 | github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 23 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 24 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 25 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 26 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 27 | github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= 28 | github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 29 | github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 30 | github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= 31 | github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 32 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 33 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 34 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 35 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 36 | github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= 37 | github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 38 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 39 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 40 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 41 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 42 | github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= 43 | github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= 44 | github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= 45 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 46 | github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= 47 | github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= 48 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 49 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 50 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 51 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 52 | github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= 53 | github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= 54 | github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 55 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 56 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 57 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 58 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 59 | github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 60 | github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= 61 | github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= 62 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 63 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 64 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 65 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 66 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 67 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 68 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 69 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 70 | github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= 71 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 72 | github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= 73 | github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= 74 | github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= 75 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 76 | go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= 77 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 78 | go.uber.org/dig v1.16.0 h1:O48QoUEj4ePocypAIE5jz+SrxVdG/izHM1CZ/Yjrwww= 79 | go.uber.org/dig v1.16.0/go.mod h1:557JTAUZT5bUK0SvCwikmLPPtdQhfvLYtO5tJgQSbnk= 80 | go.uber.org/fx v1.19.1 h1:JwYIYAQzXBuBBwSZ1/tn/95pnQO/Sp3yE8lWj9eSAzI= 81 | go.uber.org/fx v1.19.1/go.mod h1:bGK+AEy7XUwTBkqCsK/vDyFF0JJOA6X5KWpNC0e6qTA= 82 | go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= 83 | go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= 84 | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 85 | go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= 86 | go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= 87 | go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= 88 | go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY= 89 | go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY= 90 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 91 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 92 | golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= 93 | golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 94 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 95 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 96 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 97 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 98 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 99 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 100 | golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 101 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 102 | golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= 103 | golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= 104 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 105 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 106 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 107 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 108 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 109 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 110 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 111 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 112 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 113 | golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 114 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 115 | golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= 116 | golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 117 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 118 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 119 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 120 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 121 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 122 | golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= 123 | golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 124 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 125 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 126 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 127 | golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 128 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 129 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 130 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 131 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 132 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 133 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 134 | google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= 135 | google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 136 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 137 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 138 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 139 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 140 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 141 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 142 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 143 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 144 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 145 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 146 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 147 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 148 | gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc= 149 | gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= 150 | gorm.io/gorm v1.23.6/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= 151 | gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= 152 | gorm.io/gorm v1.24.3 h1:WL2ifUmzR/SLp85CSURAfybcHnGZ+yLSGSxgYXlFBHg= 153 | gorm.io/gorm v1.24.3/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= 154 | moul.io/zapgorm2 v1.2.0 h1:YdHwcqqAx658YR7YSgdX+sdyQuDRNCzRvpHLXWgOWEs= 155 | moul.io/zapgorm2 v1.2.0/go.mod h1:nPVy6U9goFKHR4s+zfSo1xVFaoU7Qgd5DoCdOfzoCqs= 156 | --------------------------------------------------------------------------------