{"id":24788882,"url":"https://github.com/abnerearl/goutils","last_synced_at":"2026-03-14T08:04:05.908Z","repository":{"id":65787281,"uuid":"599565718","full_name":"AbnerEarl/goutils","owner":"AbnerEarl","description":"Some very useful middleware libraries are re-encapsulated and are very simple and efficient to use, which can save a lot of development time, improve work efficiency and avoid duplication of code.","archived":false,"fork":false,"pushed_at":"2024-10-18T01:24:47.000Z","size":71984,"stargazers_count":3,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-10-20T13:30:45.774Z","etag":null,"topics":["develop","elasticsearch","email","encapsulated","etcd","gin","golang","http","k8s","kafka","middleware","mysql","postgres","rabbitmq","rocketmq","tool","useful","utils","web"],"latest_commit_sha":null,"homepage":"https://github.com/AbnerEarl","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AbnerEarl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-09T12:13:27.000Z","updated_at":"2024-10-18T01:24:51.000Z","dependencies_parsed_at":"2023-08-16T10:53:51.460Z","dependency_job_id":"d43833c6-bee3-4e66-9319-469174735c2a","html_url":"https://github.com/AbnerEarl/goutils","commit_stats":{"total_commits":38,"total_committers":2,"mean_commits":19.0,"dds":0.07894736842105265,"last_synced_commit":"bd34397a0d34d68d028c7378adf7af1ce6282f8b"},"previous_names":["abnerearl/goutils","youareonlyone/goutils"],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbnerEarl%2Fgoutils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbnerEarl%2Fgoutils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbnerEarl%2Fgoutils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbnerEarl%2Fgoutils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AbnerEarl","download_url":"https://codeload.github.com/AbnerEarl/goutils/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236219985,"owners_count":19114261,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["develop","elasticsearch","email","encapsulated","etcd","gin","golang","http","k8s","kafka","middleware","mysql","postgres","rabbitmq","rocketmq","tool","useful","utils","web"],"created_at":"2025-01-29T17:15:26.392Z","updated_at":"2025-10-12T13:30:23.873Z","avatar_url":"https://github.com/AbnerEarl.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n## [English](https://github.com/AbnerEarl/goutils/blob/main/README.md) ｜  [中文](https://github.com/AbnerEarl/goutils/blob/main/Chinese.md)\n\n# goutils\nSome very useful middleware libraries are re-encapsulated and are very simple and efficient to use, which can save a lot of development time, improve work efficiency and avoid duplication of code.\n\n\n## Have the ability\n- MySql stand-alone or cluster\n- PostgreSQL standalone or cluster\n- SQLite standalone or cluster\n- SQLServer stand-alone or cluster\n- TiDB stand-alone or cluster\n- Clickhouse standalone or cluster\n- Redis stand-alone or cluster\n- captcha verification code generation\n- cmdc external command call\n- datas data structure conversion\n- emails mail processing\n- elasticsearch multi-version compatible package\n- files file tool method encapsulation\n- The gins web framework is highly encapsulated\n- hook dynamic code execution\n- httpc network request client encapsulation\n- injects dependency injection and mapping\n- jwts network request authentication\n  -kafkas standalone or cluster\n- machine machine code generation\n- mongoc stand-alone or cluster\n- scripts multifunctional scripts\n- tests automated tests\n- times time and date method encapsulation\n- utils independent tool library\n- uuid unique ID generator\n-\n\n\nOther tool libraries are being gradually improved and encapsulated.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## for example\n\nMysql cluster database connection uses:\n\n```\n\npackage main\n\nimport (\n\"encoding/json\"\n\"fmt\"\n\"github.com/AbnerEarl/goutils/dbs\"\n\"time\"\n)\n\n\n\nfunc mai() {\n//Connect to the database cluster\ndsns := []string{\n\"root:password@tcp(101.152.77.55:3306)/test?charset=utf8\u0026parseTime=true\",\n\"root:password@tcp(101.159.16.231:3306)/test?charset=utf8\u0026parseTime=true\",\n\"root:password@tcp(101.159.16.88:3306)/test?charset=utf8\u0026parseTime=true\",\n}\ndb := dbs.OpenDBMySQLCluster(dsns, false, 0, 0)\n\n//Automatically create a table or update the table structure\ndb.Migration([]interface{}{\u0026dbs.UpdateModel{}})\n\n//Define an entity\nup := dbs.UpdateModel{\nFileName: \"test\",\nExecuteTime: time.Now(),\n}\n\n//Save data to database\nerr := db.Create(\u0026up)\nfmt.Println(\"create result: \", err)\n\n//Query a piece of data\nup2 := dbs.UpdateModel{}\nerr = db.RetrieveByFind(\u0026up2)\nfmt.Println(\"retrieve result: \", err)\nfmt.Println(up2)\n\n//delete data\nerr = db.DeleteHardById(\u0026up2)\nfmt.Println(\"delete result: \", err)\n\n//Batch insert into database\nvar ups = []dbs.UpdateModel{{FileName: \"uu1\", ExecuteTime: time.Now()}, {FileName: \"uu2\", ExecuteTime: time.Now()}, {FileName: \"uu3\", ExecuteTime: time.Now()}}\nerr = db.CreateBatch(ups, 100)\nfmt.Println(\"batch result: \", err)\n\n//Batch query database\nbys, count, err := db.RetrieveByWhereBytes(10, 1, \u0026dbs.UpdateModel{}, \"\", \"\", nil)\nif err != nil {\nreturn\n}\nfmt.Println(\"total count: \", count)\nvar result[]dbs.UpdateModel\njson.Unmarshal(bys, \u0026result)\nfmt.Println(result)\n}\n\n\n\n```\n\n\n```\n\ngo run main.go\n\n\n```\n\n\n\n```\n\ncreate result: \u003cnil\u003e\nretrieve result: \u003cnil\u003e\n{{3 0 2024-01-09 07:25:16.067 +0000 UTC 2024-01-09 07:25:16.067 +0000 UTC \u003cnil\u003e } test 2024-01-09 07:25:16.036 +0000 UTC}\ndelete result: \u003cnil\u003e\nbatch result: \u003cnil\u003e\ntotal count: 16\n[{{6 0 2024-01-09 07:25:16.224 +0000 UTC 2024-01-09 07:25:16.224 +0000 UTC \u003cnil\u003e } uu1 2024-01-09 07:25:16.194 +0000 UTC} {{9 0 2024-01-09 07:25:16.224 +0000 UTC 2024-01-09 07:25:16.224 +0000 UTC \u003cnil\u003e } uu2 2024-01-09 07:25:16.194 +0000 UTC} { {12 0 2024-01-09 07:25:16.224 +0000 UTC 2024-01-09 07:25:16.224 +0000 UTC \u003cnil\u003e } uu3 2024-01-09 07:25:16.194 +0000 UTC} {{ 14 0 2024-01-09 07:35:35.615 +0000 UTC 2024-01-09 07:35:35.615 +0000 UTC \u003cnil\u003e } test222 2024-01-09 07:35:35.585 +0000 UTC} {{16 0 2024-01-09 07:35:35.781 +0000 UTC 2024-01-09 07:35:35.781 +0000 UTC \u003cnil\u003e } uu1 2024-01-09 07:35:35.751 +0000 UTC} {{18 0 2024-01-09 07:35:35.781 +0000 UTC 2024-01-09 07:35:35.781 +0000 UTC \u003cnil\u003e } uu2 2024-01-09 07:35:35.751 +0000 UTC} {{20 0 2024 -01-09 07:35:35.781 +0000 UTC 2024-01-09 07:35:35.781 +0000 UTC \u003cnil\u003e } uu3 2024-01-09 07:35:35.751 +0000 UTC} {{21 0 2024- 01-09 07:41:35.85 +0000 UTC 2024-01-09 07:41:35.85 +0000 UTC \u003cnil\u003e } test333 2024-01-09 07:41:35.819 +0000 UTC} {{23 0 2024-01 -09 08:03:15.64 +0000 UTC 2024-01-09 08:03:15.64 +0000 UTC \u003cnil\u003e } test4444 2024-01-09 08:03:15.587 +0000 UTC} {{25 0 2024-01- 09 08:03:15.881 +0000 UTC 2024-01-09 08:03:15.881 +0000 UTC \u003cnil\u003e } uu1 2024-01-09 08:03:15.837 +0000 UTC}]\n\n\n```\n\n\n\n## Main method\n\nEach tool library encapsulates a number of methods, which can be viewed under the corresponding package. Taking the use of dbs database as an example, the Create,Retrieve,Update,Delete (CRUD) method is complete. Some method examples are as follows:\n\n```\n\nfunc (m *BaseModel) BeforeCreate(fc func(tx *TX) error, db *DB) error {\nfunc (m *BaseModel) AfterCreate(fc func(tx *TX) error, db *DB) error {\nfunc (m *BaseModel) BeforeSave(fc func(tx *TX) error, db *DB) error {\nfunc (m *BaseModel) AfterSave(fc func(tx *TX) error, db *DB) error {\nfunc (m *BaseModel) BeforeUpdate(fc func(tx *TX) error, db *DB) error {\nfunc (m *BaseModel) AfterUpdate(fc func(tx *TX) error, db *DB) error {\nfunc (m *BaseModel) BeforeDelete(fc func(tx *TX) error, db *DB) error {\nfunc (m *BaseModel) AfterDelete(fc func(tx *TX) error, db *DB) error {\nfunc (db *DB) Create(dataModel interface{}) error {\nfunc (db *DB) CreateBatch(dataModels interface{}, batchSize uint) error {\nfunc (db *DB) UpdateById(dataModel interface{}) error {\nfunc (db *DB) UpdateByWhereModel(where string, updateModel interface{}) error {\nfunc (db *DB) UpdateByArgsWhereModel(where string, args []interface{}, updateModel interface{}) error {\nfunc (db *DB) UpdateByWhere(dataModel interface{}, where string, updates map[string]interface{}) error {\nfunc (db *DB) UpdateByModelWhere(whereModel interface{}, updates map[string]interface{}) error {\nfunc (db *DB) UpdateByModelWhereModel(whereModel interface{}, updateModel interface{}) error {\nfunc (db *DB) UpdateByArgsWhere(dataModel interface{}, where string, args []interface{}, updates map[string]interface{}) error {\nfunc (db *DB) UpdateByField(dataModel interface{}, where interface{}, column, expr string, updates ...interface{}) error {\nfunc (db *DB) UpdateByArgsField(dataModel interface{}, where string, args []interface{}, column, expr string, updates ...interface{}) error {\nfunc (db *DB) UpdateByModelField(whereModel interface{}, column, expr string, updates ...interface{}) error {\nfunc (db *DB) DeleteHardById(dataModels interface{}) error {\nfunc (db *DB) DeleteSoftById(dataModels interface{}) error {\nfunc (db *DB) DeleteHardByWhere(dataModel interface{}, where string, args []interface{}) error {\nfunc (db *DB) DeleteSoftByWhere(dataModel interface{}, where string, args []interface{}) error {\nfunc (db *DB) RetrieveById(whereModel interface{}) error {\nfunc (db *DB) RetrieveByFind(whereModel interface{}) error {\nfunc (db *DB) RetrieveByMap(dataModel interface{}, whereMap map[string]interface{}) error {\nfunc (db *DB) RetrieveByArgs(dataModel interface{}, where string, args []interface{}) error {\nfunc (db *DB) RetrieveCountByArgs(dataModel interface{}, where string, args []interface{}) (int64, error) {\nfunc (db *DB) RetrieveCountByModel(whereModel interface{}) (int64, error) {\nfunc (db *DB) RetrieveByWhere(pageSize, pageNo int, dataModel interface{}, order, where string, args []interface{}) (interface{}, int64, error) {\nfunc (db *DB) RetrieveByWhereString(pageSize, pageNo int, dataModel interface{}, order, where string, args []interface{}) (string, int64, error) {\nfunc (db *DB) RetrieveByWhereBytes(pageSize, pageNo int, dataModel interface{}, order, where string, args []interface{}) ([]byte, int64, error) {\nfunc (db *DB) RetrieveByWhereSelect(pageSize, pageNo int, dataModel interface{}, fields []string, order, where string, args []interface{}) (interface{}, int64, error) {\nfunc (db *DB) RetrieveByWhereSelectString(pageSize, pageNo int, dataModel interface{}, fields []string, order, where string, args []interface{}) (string, int64, error) {\nfunc (db *DB) RetrieveByWhereSelectBytes(pageSize, pageNo int, dataModel interface{}, fields []string, order, where string, args []interface{}) ([]byte, int64, error) {\nfunc (db *DB) RawSqlForMap(sql string, values ...interface{}) ([]map[string]interface{}, error) {\nfunc (db *DB) RawSqlForByte(sql string, values ...interface{}) ([]byte, error) {\nfunc Rows2Map(rows *sql.Rows) []map[string]interface{} {\nfunc Rows2Bytes(rows *sql.Rows) []byte {\nfunc (db *DB) Exec(sql string, values ...interface{}) error {\nfunc (db *DB) RetrieveByModel(pageSize, pageNo int, whereModel interface{}, order string) (interface{}, int64, error) {\nfunc (db *DB) RetrieveByModelString(pageSize, pageNo int, whereModel interface{}, order string) (string, int64, error) {\nfunc (db *DB) RetrieveByModelBytes(pageSize, pageNo int, whereModel interface{}, order string) ([]byte, int64, error) {\nfunc (db *DB) RetrieveByModelSelect(pageSize, pageNo int, whereModel interface{}, fields []string, order string) (interface{}, int64, error) {\nfunc (db *DB) RetrieveByModelSelectString(pageSize, pageNo int, whereModel interface{}, fields []string, order string) (string, int64, error) {\nfunc (db *DB) RetrieveByModelSelectBytes(pageSize, pageNo int, whereModel interface{}, fields []string, order string) ([]byte, int64, error) {\nfunc (db *DB) Transaction(fc func(tx *TX) error) error {\n\n\n```\n\n\n\nIn order to better use automatic association methods, it is necessary to pay attention to some rules, such as first defining a model:\n\n```\n/**\n * @author: yangchangjia\n * @email 1320259466@qq.com\n * @date: 2024/8/14 15:55\n * @desc: about the role of class.\n */\n\npackage model\n\nimport (\n\t\"projectname/config\"\n\t\"github.com/AbnerEarl/goutils/dbs\"\n\t\"github.com/AbnerEarl/goutils/web\"\n\t\"gorm.io/gorm\"\n)\n\ntype ShopModel struct {\n\tdbs.BaseModel\n\tUserId        uint64  `json:\"user_id\" gorm:\"column:user_id;not null;comment:'用户ID'\"`\n\tName          string  `json:\"name\" gorm:\"column:name;not null;comment:'名称'\"`\n\tImage         string  `json:\"image\" gorm:\"column:image;not null;comment:'店铺照片'\"`\n\tLocation      string  `json:\"location\" gorm:\"column:location;not null;comment:'位置'\"`\n\tLongitude     float64 `json:\"longitude\" gorm:\"column:longitude;not null;comment:'经度'\"`\n\tLatitude      float64 `json:\"latitude\" gorm:\"column:latitude;not null;comment:'纬度'\"`\n\tPhone         string  `json:\"phone\" gorm:\"column:phone;not null;comment:'电话'\"`\n\tWorkTime      string  `json:\"work_time\" gorm:\"column:work_time;not null;comment:'营业时间'\"`\n\tWorkStartTime string  `json:\"work_start_time\" gorm:\"column:work_start_time;not null;comment:'营业开始时间'\"`\n\tWorkEndTime   string  `json:\"work_end_time\" gorm:\"column:work_end_time;not null;comment:'营业结束时间'\"`\n\tWorkStatus    uint    `json:\"work_status\" gorm:\"column:work_status;default:0;not null;comment:'营业状态'\"`\n\tStatus        uint    `json:\"status\" gorm:\"column:status;default:1;not null;comment:'店铺状态'\"`\n}\n\nfunc (m *ShopModel) TableName() string {\n\treturn \"shop_info\"\n}\n\n// For the sake of data security and efficiency, an irregular monotonically increasing integer is used as the primary key ID,\n// which is mainly improved based on the Snow Flower algorithm, Pear Blossom algorithm, and Mist algorithm.\nfunc (m *ShopModel) BeforeCreate(db *gorm.DB) error {\n\tm.Id = web.GenAutoIdByKeyClu(config.RedisCli, web.AUTO_ID_GENERATOR_COUNTER_KEY+m.TableName())\n\treturn nil\n}\n\n```\n\n\nThere is no need to define other methods, as this model already inherits most of the CRUD related methods.\n\nAutomatically generate relevant documents, including dictionaries, API documents, etc. You can use them by creating a gen.go file in the project root directory or main file directory, and entering the following content:\n\n```\n/**\n * @author: yangchangjia\n * @email 1320259466@qq.com\n * @date: 2024/7/4 09:21\n * @desc: about the role of class.\n */\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/AbnerEarl/goutils/files\"\n\t\"github.com/AbnerEarl/goutils/scripts\"\n\t\"github.com/AbnerEarl/goutils/swag\"\n)\n\nfunc main() {\n\terr := scripts.GenDbComment(files.GetCuPath()+\"/model\", \"base\", \"comment.go\")\n\tif err != nil {\n\t\tfmt.Println(\"GenDbComment: \", err)\n\t}\n\n\terr = swag.InstallSwag()\n\tif err != nil {\n\t\tfmt.Println(\"InstallSwag: \", err)\n\t}\n\n\terr = swag.GenSwagDoc(\"shop.go\", \"./api/shop\", nil)\n\tif err != nil {\n\t\tfmt.Println(\"GenSwagDoc: \", err)\n\t}\n\n}\n\n```\n\nThe content example of the main file for the project entrance is as follows:\n\n```\npackage main\n\nimport (\n\t\"projectname/config\"\n\t_ \"projectname/docs\"\n\t\"projectname/model\"\n\t\"projectname/router\"\n\t\"projectname/task\"\n\t\"github.com/AbnerEarl/goutils/gins\"\n\t\"github.com/spf13/pflag\"\n\t\"github.com/spf13/viper\"\n\tswaggerFiles \"github.com/swaggo/files\"\n\tginSwagger \"github.com/swaggo/gin-swagger\"\n\t\"go.uber.org/zap\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n)\n\nvar (\n\tcfgShop = pflag.StringP(\"config\", \"c\", \"etc/config_shop.yaml\", \"project config\")\n)\n\n// @title 项目API文档\n// @version 1.0\n// @description 项目前后端联调及测试API文档。\n// @termsOfService https://github.com\n// @contact.name API Support\n// @contact.url http://www.cnblogs.com\n// @contact.email ×××@qq.com\n// @securityDefinitions.apikey ApiKeyAuth\n// @in header\n// @name token\n// @BasePath /api/v1\nfunc main() {\n\tpflag.Parse()\n\n\tif err := config.Init(*cfgShop); err != nil {\n\t\tpanic(err)\n\t}\n\tmode := viper.GetString(\"web.runmode\")\n\taddr := viper.GetString(\"web.addr\")\n\tlogCycle := viper.GetInt(\"log.cycle\")\n\taddrs := viper.GetStringSlice(\"rs.addrs\")\n\tpassword := viper.GetString(\"rs.password\")\n\n\texitChan := make(chan int)\n\tsignalChan := make(chan os.Signal, 1)\n\tgo func() {\n\t\t\u003c-signalChan\n\t\texitChan \u003c- 1\n\t}()\n\n\tsignal.Notify(signalChan, syscall.SIGINT, syscall.SIGKILL)\n\n\tmodel.InitDb()\n\tconfig.InitRedis(addrs, password)\n\n\tgo task.PeriodicTasks(logCycle)\n\n\tg := gins.DefaultServer(mode)\n\tg.Engine.GET(\"/swagger/*any\", ginSwagger.WrapHandler(swaggerFiles.Handler))\n\trouter.LoadShop(g)\n\tgo func() {\n\t\tzap.L().Info(http.ListenAndServe(addr, g).Error())\n\t}()\n\n\t\u003c-exitChan\n\n}\n\n```\n\nThe example of file directory structure is as follows:\n\n```\n├── README.en.md\n├── README.md\n├── api\n├── base\n├── conf\n├── config\n├── docs\n├── etc\n├── gen.go\n├── go.mod\n├── go.sum\n├── lib\n├── main.go\n├── model\n├── router\n├── scripts\n├── service\n├── shop.go\n└── task\n\n```\n\n\nFinally, execute the gen.go file to generate the relevant dictionary and API interface documents, as shown in the following example:\n\n```\ngo run gen.go \n\n```\n\n----\n\nFor other tool library usage, you can view relevant documents in the docs directory.\n\n\n\n## Related instructions\n\nInterested friends are welcome to participate or make valuable suggestions.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabnerearl%2Fgoutils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabnerearl%2Fgoutils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabnerearl%2Fgoutils/lists"}