{"id":21113460,"url":"https://github.com/phamtai97/go-utils","last_synced_at":"2025-07-08T18:31:53.506Z","repository":{"id":57628540,"uuid":"404403705","full_name":"phamtai97/go-utils","owner":"phamtai97","description":"Set of reusable components for Golang projects","archived":false,"fork":false,"pushed_at":"2021-10-06T15:38:46.000Z","size":81,"stargazers_count":7,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-04T08:11:49.487Z","etag":null,"topics":["config","convertor","datetime","error","golang","logger"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phamtai97.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}},"created_at":"2021-09-08T15:39:44.000Z","updated_at":"2024-11-19T15:26:17.000Z","dependencies_parsed_at":"2022-09-26T20:12:09.184Z","dependency_job_id":null,"html_url":"https://github.com/phamtai97/go-utils","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/phamtai97/go-utils","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phamtai97%2Fgo-utils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phamtai97%2Fgo-utils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phamtai97%2Fgo-utils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phamtai97%2Fgo-utils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phamtai97","download_url":"https://codeload.github.com/phamtai97/go-utils/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phamtai97%2Fgo-utils/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264323942,"owners_count":23590771,"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":["config","convertor","datetime","error","golang","logger"],"created_at":"2024-11-20T01:43:56.934Z","updated_at":"2025-07-08T18:31:48.688Z","avatar_url":"https://github.com/phamtai97.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# go-utils\n[![Go Report Card](https://goreportcard.com/badge/github.com/phamtai97/go-utils)](https://goreportcard.com/report/github.com/phamtai97/go-utils) [![Go Reference](https://pkg.go.dev/badge/github.com/phamtai97/go-utils.svg)](https://pkg.go.dev/github.com/phamtai97/go-utils)\n\n## Table of contents\n- [go-utils](#go-utils)\n  - [Table of contents](#table-of-contents)\n  - [1. Overview](#1-overview)\n  - [2. Install](#2-install)\n  - [3. Utils package](#3-utils-package)\n    - [3.1 logger](#31-logger)\n    - [3.2 error](#32-error)\n    - [3.3 datetime](#33-datetime)\n    - [3.4 config](#34-config)\n    - [3.5 conv](#35-conv)\n    - [3.6 database](#36-database)\n## 1. Overview\nIn my free time, I will learn new knowledge about Golang and make notes on this project, or more simply, I will write my own components that can be reused for many different projects. This helped me review my knowledge of Golang as well as gain more experience on how to use this language.\n\n## 2. Install\n- Run command `go get`.\n\n```sh\ngo get github.com/phamtai97/go-utils\n```\n## 3. Utils package\n### [3.1 logger](./utils/logger/logger.go) \n- I have wrapped the [zap](https://github.com/uber-go/zap) library for easy use in projects. Why zap? Because it is very [fast](https://github.com/uber-go/zap#performance).\n- How to use?\n- We only need to create it once and use it anywhere in the project. For example:\n\n```go\n...\nfunc main(){\n    // write log to console\n    // logger.InitProduction(\"\")\n\n    // write log to logs.log file\n    if err := logger.InitProduction(\"./logs.log\"); err != nil {\n        fmt.Printf(\"Failed to init logger: %v\\n\", err)\n    }\n    defer logger.Sync()\n\n    logger.Info(\"I am AJPham\",\n        zap.String(\"Hey, \", \"I am a software engineer\"),\n        zap.Int(\"Age: \", 1997))\n    logger.Error(\"I am AJPham\",\n        zap.String(\"Hey, \", \"I am a software engineer\"),\n        zap.Int(\"Age: \", 1997))\n}\n\n// Result in file logs.log\n// {\"level\":\"INFO\",\"ts\":\"2021-09-10 21:52:04.176\",\"caller\":\"error/main.go:65\",\"msg\":\"I am AJPham\",\"Hey, \":\"I am a software engineer\",\"Age: \":1997}\n// {\"level\":\"ERROR\",\"ts\":\"2021-09-10 21:52:04.176\",\"caller\":\"error/main.go:69\",\"msg\":\"I am AJPham\",\"Hey, \":\"I am a software engineer\",\"Age: \":1997,\"stacktrace\":\"main.main\\n\\t/Users/Documents/github/go-utils/cmd/error/main.go:69\\nruntime.main\\n\\t/usr/local/Cellar/go@1.13/1.13.11/libexec/src/runtime/proc.go:203\"}\n```\n\n- Detailed examples can be see [here](cmd/logger/main.go).\n\n### [3.2 error](./utils/error/error.go)\n- This is a simple way to create errors in the project. It uses the [github.com/pkg/errors](https://github.com/pkg/errors) package as the core.\n- How to use?\n- We can new error and use it. For example:\n\n```go\n...\nfunc main() {\n    logger.InitProduction(\"\")\n\n    err := ero.New(\"Not found file\")\n    errA := err.AddStackTrace(\"Component A called\")\n    errB := errA.AddContextf(\"Component %s called\", \"B\")\n\n    if errB.Is(err) {\n        logger.Info(\"Error B is err\")\n    }\n\n    logger.Error(\"This is error wrapper\", zap.Error(errB))\n    logger.Error(\"This is error detail wrapper\", zap.Error(errB.Detail()))\n    logger.Error(\"This is root cause\", zap.Error(errB.RootCause().Detail()))\n    logger.Error(\"This is root cause\", zap.String(\"Error string\", err.Error()))\n}\n\n// Result\n// {\"level\":\"INFO\",\"ts\":\"2021-09-10 21:55:29.840\",\"caller\":\"error/main.go:66\",\"msg\":\"Error B is err\"}\n// {\"level\":\"ERROR\",\"ts\":\"2021-09-10 21:50:15.523\",\"caller\":\"error/main.go:65\",\"msg\":\"This is error wrapper\",\"error\":\"Component B called: Component A called: Not found file\",\"stacktrace\":\"main.main\\n\\t/Users/Documents/github/go-utils/cmd/error/main.go:65\\nruntime.main\\n\\t/usr/local/Cellar/go@1.13/1.13.11/libexec/src/runtime/proc.go:203\"}\n// {\"level\":\"ERROR\",\"ts\":\"2021-09-10 21:50:15.523\",\"caller\":\"error/main.go:66\",\"msg\":\"This is error detail wrapper\",\"error\":\"Component B called: Component A called: Not found file\",\"errorVerbose\":\"Not found file\\ngo-utils/utils/error.New\\n\\t/Users/Documents/github/go-utils/utils/error/error.go:17\\nmain.main\\n\\t/Users/Documents/github/go-utils/cmd/error/main.go:61\\nruntime.main\\n\\t/usr/local/Cellar/go@1.13/1.13.11/libexec/src/runtime/proc.go:203\\nruntime.goexit\\n\\t/usr/local/Cellar/go@1.13/1.13.11/libexec/src/runtime/asm_amd64.s:1357\\nComponent A called\\ngo-utils/utils/error.(*ErrorWrapper).AddStackTrace\\n\\t/Users/Documents/github/go-utils/utils/error/error.go:47\\nmain.main\\n\\t/Users/Documents/github/go-utils/cmd/error/main.go:62\\nruntime.main\\n\\t/usr/local/Cellar/go@1.13/1.13.11/libexec/src/runtime/proc.go:203\\nruntime.goexit\\n\\t/usr/local/Cellar/go@1.13/1.13.11/libexec/src/runtime/asm_amd64.s:1357\\nComponent B called\",\"stacktrace\":\"main.main\\n\\t/Users/Documents/github/go-utils/cmd/error/main.go:66\\nruntime.main\\n\\t/usr/local/Cellar/go@1.13/1.13.11/libexec/src/runtime/proc.go:203\"}\n// {\"level\":\"ERROR\",\"ts\":\"2021-09-10 21:50:15.523\",\"caller\":\"error/main.go:67\",\"msg\":\"This is root cause\",\"error\":\"Not found file\",\"errorVerbose\":\"Not found file\\ngo-utils/utils/error.New\\n\\t/Users/Documents/github/go-utils/utils/error/error.go:17\\nmain.main\\n\\t/Users/Documents/github/go-utils/cmd/error/main.go:61\\nruntime.main\\n\\t/usr/local/Cellar/go@1.13/1.13.11/libexec/src/runtime/proc.go:203\\nruntime.goexit\\n\\t/usr/local/Cellar/go@1.13/1.13.11/libexec/src/runtime/asm_amd64.s:1357\",\"stacktrace\":\"main.main\\n\\t/Users/Documents/github/go-utils/cmd/error/main.go:67\\nruntime.main\\n\\t/usr/local/Cellar/go@1.13/1.13.11/libexec/src/runtime/proc.go:203\"}\n// {\"level\":\"ERROR\",\"ts\":\"2021-09-10 21:50:15.523\",\"caller\":\"error/main.go:68\",\"msg\":\"This is root cause\",\"Error string\":\"Not found file\",\"stacktrace\":\"main.main\\n\\t/Users/Documents/github/go-utils/cmd/error/main.go:68\\nruntime.main\\n\\t/usr/local/Cellar/go@1.13/1.13.11/libexec/src/runtime/proc.go:203\"}\n```\n\n- Detailed examples can be see [here](cmd/error/main.go).\n\n### [3.3 datetime](./utils/datetime/datetime.go)\n- Working with Datetime in programming is inevitable. I provide a simple enough package to play with Datetime in Golang.\n- How to use?\n- It is easy.\n\n```go\nfunc main() {\n    logger.InitProduction(\"\")\n\n    // Convert current milliseconds to different formats\n    logger.Info(\"Convert current milliseconds to format YYYY-MM-DD\", zap.String(\"value\", datetime.ConvertCurrentLocalTimeToString(datetime.YYYY_MM_DD)))\n    logger.Info(\"Convert current milliseconds to format YYYY-MM-DD HH:mm:ss\", zap.String(\"value\", datetime.ConvertCurrentLocalTimeToString(datetime.YYYY_MM_DD_HH_MM_SS)))\n    logger.Info(\"Convert current milliseconds to format YYYY-MM-DD HH:mm:ss.SSS\", zap.String(\"value\", datetime.ConvertCurrentLocalTimeToString(datetime.YYYY_MM_DD_HH_MM_SS_SSS)))\n    logger.Info(\"Convert current milliseconds to format DD-MM-YYYY\", zap.String(\"value\", datetime.ConvertCurrentLocalTimeToString(datetime.DD_MM_YYYY)))\n    logger.Info(\"Convert current milliseconds to format DD-MM-YYYY HH:mm:ss\", zap.String(\"value\", datetime.ConvertCurrentLocalTimeToString(datetime.DD_MM_YYYY_HH_MM_SS)))\n    logger.Info(\"Convert current milliseconds to format DD-MM-YYYY HH:mm:ss.SSS\", zap.String(\"value\", datetime.ConvertCurrentLocalTimeToString(datetime.DD_MM_YYYY_HH_MM_SS_SSS)))\n\n    // Get current millisenconds\n    currMillis := datetime.GetCurrentMiliseconds()\n    logger.Info(\"Current milliseconds\", zap.Int64(\"value\", millis))\n\n    // Convert milliseconds to specific string\n    ddmmyyyy_hhmmss_sss := datetime.ConvertMillisecondsToString(currMillis, datetime.DD_MM_YYYY_HH_MM_SS_SSS)\n    logger.Info(\"Convert milliseconds to format DD-MM-YYYY HH:mm:ss.SSS\", zap.String(\"value\", ddmmyyyy_hhmmss_sss))\n\n    // Convert specific string to milliseconds\n    millis, err := datetime.ConvertStringToMilliseconds(\"2021-09-09 09:09:09.999\", datetime.YYYY_MM_DD_HH_MM_SS_SSS)\n    if err != nil{\n        logger.Error(\"Failed to convert\", zap.Error(err))\n    }\n    logger.Info(\"Convert string format YYYY-MM-DD HH:mm:ss.SSS to millisecond\", zap.Int64(\"value\", millis))\n\n    // other functions\n    logger.Info(\"Start local time of year\", zap.Int64(\"value\", datetime.ConvertLocalTimeToMilliseconds(datetime.GetStartLocalTimeOfYear())))\n    logger.Info(\"End local time of year\", zap.Int64(\"value\", datetime.ConvertLocalTimeToMilliseconds(datetime.GetEndLocalTimeOfYear())))\n    logger.Info(\"Start local time of month\", zap.Int64(\"value\", datetime.ConvertLocalTimeToMilliseconds(datetime.GetStartLocalTimeOfMonth())))\n    logger.Info(\"End local time of month\", zap.Int64(\"value\", datetime.ConvertLocalTimeToMilliseconds(datetime.GetEndLocalTimeOfMonth())))\n    logger.Info(\"Start local time of day\", zap.Int64(\"value\", datetime.ConvertLocalTimeToMilliseconds(datetime.GetStartLocalTimeOfDay())))\n    logger.Info(\"End local time of day\", zap.Int64(\"value\", datetime.ConvertLocalTimeToMilliseconds(datetime.GetEndLocalTimeOfDay())))\n    logger.Info(\"Start local time of time\", zap.Int64(\"value\", datetime.ConvertLocalTimeToMilliseconds(datetime.GetStartLocalTimeOfTime(time.Now()))))\n    logger.Info(\"Start local time of time\", zap.Int64(\"value\", datetime.ConvertLocalTimeToMilliseconds(datetime.GetEndLocalTimeOfTime(time.Now()))))\n    logger.Info(\"Get before local time of time\", zap.Int64(\"value\", datetime.ConvertLocalTimeToMilliseconds(datetime.GetBeforeLocalTimeOfTime(time.Now(), 9, true))))\n    logger.Info(\"Get after local time of time\", zap.Int64(\"value\", datetime.ConvertLocalTimeToMilliseconds(datetime.GetAfterLocalTimeOfTime(time.Now(), 9, false))))\n}\n```\n\n- Detailed examples can be see [here](cmd/datetime/main.go).\n\n### [3.4 config](./utils/config/config.go)\n- Most applications need configuration to run (except very simple ones). We can manage configuration by file such as yaml, json file. The package provides a way to load configuration from yaml and json files and parse it into an object.\n- How to use?\n- Let's go.\n\n```go\nfunc main() {\n    logger.InitProduction(\"\")\n    serviceConfig := ServiceConfig{}\n\n    // Load config from yaml file\n    if err := config.Load(\u0026serviceConfig, \"dev.yaml\"); err != nil {\n        logger.Fatal(\"Failed to load config\", zap.Error(err))\n    }\n\n    // We can provide path of config by flag to load config\n    if err := config.LoadByFlag(\u0026serviceConfig, \"cfgPath\"); err != nil {\n        logger.Fatal(\"Failed to load config\", zap.Error(err))\n    }\n\n    // Load config from json file\n    if err := config.Load(\u0026serviceConfig, \"dev.json\"); err != nil {\n        logger.Fatal(\"Failed to load config\", zap.Error(err))\n    }\n\n    // If you want omit hotkeys such as token, password,...\n    if err := config.Print(serviceConfig, \"Token\", \"Password\"); err != nil {\n        logger.Fatal(\"Failed to print config\", zap.Error(err))\n    }\n}\n```\n- Detailed examples can be see [here](./cmd/config/main.go).\n\n### [3.5 conv](./utils/convertor/convertor.go)\n- How to convert numbers and strings? How to convert string to number? It's simple because there's a convertor package.\n- I use [strconv](https://pkg.go.dev/strconv) for conv package.\n- It includes the following data types: int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, bool.\n- How to use?\n- Don't go to google looking for ways to convert anymore.\n\n```go\nfunc main() {\n    logger.InitProduction(\"\")\n\n    numInt, err := conv.ConvertStringToInt(\"123456\")\n    if err != nil {\n        logger.Fatal(\"Failed to convert string to int\")\n    }\n    logger.Info(\"Convert string to int\", zap.Int(\"Value\", numInt))\n\n    strInt := conv.ConvertIntToString(123456)\n    logger.Info(\"Convert int to string\", zap.String(\"Value\", strUInt))\n}\n```\n\n- Detailed examples can be see [here](./cmd/convertor/main.go).\n\n### [3.6 database](./utils/db/database.go)\n- There are many libraries that support working with different databases. \n- Using the Database interface and you can implement datasource packages such as mysql, postgresql.\n- Example: I use [sqlx](https://github.com/jmoiron/sqlx) to work with mysql and implement MySQLImpl struct.\n- How to use?\n- This is the most approachable I've ever done.\n  \n```go\n// AccountDTO data transfer object\ntype AccountDTO struct {\n\tID          int64  `db:\"id\"`\n\tUsername    string `db:\"username\"`\n\tPassword    string `db:\"password\"`\n\tEmail       string `db:\"email\"`\n\tStatus      int    `db:\"status\"`\n\tRole        string `db:\"role\"`\n\tCreatedTime int64  `db:\"created_time\"`\n\tUpdatedTime int64  `db:\"updated_time\"`\n}\n\nfunc main() {\n    logger.InitProduction(\"\")\n\n    config := database.MySQLConfig{\n        User:                      \"dbgtest\",\n        Password:                  \"abc@123\",\n        Host:                      \"10.30.17.173\",\n        Port:                      4000,\n        DBName:                    \"go_admin\",\n        PoolName:                  \"account_da\",\n        PoolSize:                  10,\n        MaxIdleConns:              2,\n        ConnMaxLifetimeInMs:       10000,\n        ReadTimeoutInMs:           3000,\n        WriteTimeoutInMs:          3000,\n        DialConnectionTimeoutInMs: 3000,\n    }\n\n    mysql, err := database.NewMySQLImpl(config)\n    if err != nil {\n        logger.Fatal(\"Failed to create mysql\", zap.Error(err))\n    }\n    defer mysql.Disconnect()\n\n    db := mysql.GetConnection().(*sqlx.DB)\n\n    //\n    // Insert new account into DB\n    newAccount := AccountDTO{\n        Username:    \"AJPham\",\n        Password:    \"123@ajpham\",\n        Email:       \"go-util@gmail.com\",\n        Status:      1,\n        Role:        \"admin\",\n        CreatedTime: datetime.GetCurrentMiliseconds(),\n        UpdatedTime: datetime.GetCurrentMiliseconds(),\n    }\n\n    resultInsert, err := db.Exec(\"INSERT INTO account (username, password, email, status, role, created_time, updated_time) VALUES (?, ?, ?, ?, ?, ?, ?)\",\n        newAccount.Username, newAccount.Password, newAccount.Email, newAccount.Status, newAccount.Role, newAccount.CreatedTime, newAccount.UpdatedTime)\n    if err != nil {\n        logger.Fatal(\"Failed to insert new account\", zap.Error(err))\n    }\n\n    rowInserted, err := resultInsert.RowsAffected()\n    if err != nil {\n        logger.Fatal(\"Failed to insert new account\", zap.Error(err))\n    }\n    logger.Info(\"Insert account successed\", zap.Int64(\"Row affected\", rowInserted))\n```\n\n- Detailed examples can be see [here](./cmd/db/main.go).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphamtai97%2Fgo-utils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphamtai97%2Fgo-utils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphamtai97%2Fgo-utils/lists"}