utils

package module
v0.6.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 6, 2021 License: MIT Imports: 0 Imported by: 0

README

go-utils

Go Report Card Go Reference

Table of contents

1. Overview

In 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.

2. Install

  • Run command go get.
go get github.com/phamtai97/go-utils

3. Utils package

3.1 logger
  • I have wrapped the zap library for easy use in projects. Why zap? Because it is very fast.
  • How to use?
  • We only need to create it once and use it anywhere in the project. For example:
...
func main(){
    // write log to console
    // logger.InitProduction("")

    // write log to logs.log file
    if err := logger.InitProduction("./logs.log"); err != nil {
        fmt.Printf("Failed to init logger: %v\n", err)
    }
    defer logger.Sync()

    logger.Info("I am AJPham",
        zap.String("Hey, ", "I am a software engineer"),
        zap.Int("Age: ", 1997))
    logger.Error("I am AJPham",
        zap.String("Hey, ", "I am a software engineer"),
        zap.Int("Age: ", 1997))
}

// Result in file logs.log
// {"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}
// {"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"}
  • Detailed examples can be see here.
3.2 error
  • This is a simple way to create errors in the project. It uses the github.com/pkg/errors package as the core.
  • How to use?
  • We can new error and use it. For example:
...
func main() {
    logger.InitProduction("")

    err := ero.New("Not found file")
    errA := err.AddStackTrace("Component A called")
    errB := errA.AddContextf("Component %s called", "B")

    if errB.Is(err) {
        logger.Info("Error B is err")
    }

    logger.Error("This is error wrapper", zap.Error(errB))
    logger.Error("This is error detail wrapper", zap.Error(errB.Detail()))
    logger.Error("This is root cause", zap.Error(errB.RootCause().Detail()))
    logger.Error("This is root cause", zap.String("Error string", err.Error()))
}

// Result
// {"level":"INFO","ts":"2021-09-10 21:55:29.840","caller":"error/main.go:66","msg":"Error B is err"}
// {"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"}
// {"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"}
// {"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"}
// {"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"}
  • Detailed examples can be see here.
3.3 datetime
  • Working with Datetime in programming is inevitable. I provide a simple enough package to play with Datetime in Golang.
  • How to use?
  • It is easy.
func main() {
    logger.InitProduction("")

    // Convert current milliseconds to different formats
    logger.Info("Convert current milliseconds to format YYYY-MM-DD", zap.String("value", datetime.ConvertCurrentLocalTimeToString(datetime.YYYY_MM_DD)))
    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)))
    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)))
    logger.Info("Convert current milliseconds to format DD-MM-YYYY", zap.String("value", datetime.ConvertCurrentLocalTimeToString(datetime.DD_MM_YYYY)))
    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)))
    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)))

    // Get current millisenconds
    currMillis := datetime.GetCurrentMiliseconds()
    logger.Info("Current milliseconds", zap.Int64("value", millis))

    // Convert milliseconds to specific string
    ddmmyyyy_hhmmss_sss := datetime.ConvertMillisecondsToString(currMillis, datetime.DD_MM_YYYY_HH_MM_SS_SSS)
    logger.Info("Convert milliseconds to format DD-MM-YYYY HH:mm:ss.SSS", zap.String("value", ddmmyyyy_hhmmss_sss))

    // Convert specific string to milliseconds
    millis, err := datetime.ConvertStringToMilliseconds("2021-09-09 09:09:09.999", datetime.YYYY_MM_DD_HH_MM_SS_SSS)
    if err != nil{
        logger.Error("Failed to convert", zap.Error(err))
    }
    logger.Info("Convert string format YYYY-MM-DD HH:mm:ss.SSS to millisecond", zap.Int64("value", millis))

    // other functions
    logger.Info("Start local time of year", zap.Int64("value", datetime.ConvertLocalTimeToMilliseconds(datetime.GetStartLocalTimeOfYear())))
    logger.Info("End local time of year", zap.Int64("value", datetime.ConvertLocalTimeToMilliseconds(datetime.GetEndLocalTimeOfYear())))
    logger.Info("Start local time of month", zap.Int64("value", datetime.ConvertLocalTimeToMilliseconds(datetime.GetStartLocalTimeOfMonth())))
    logger.Info("End local time of month", zap.Int64("value", datetime.ConvertLocalTimeToMilliseconds(datetime.GetEndLocalTimeOfMonth())))
    logger.Info("Start local time of day", zap.Int64("value", datetime.ConvertLocalTimeToMilliseconds(datetime.GetStartLocalTimeOfDay())))
    logger.Info("End local time of day", zap.Int64("value", datetime.ConvertLocalTimeToMilliseconds(datetime.GetEndLocalTimeOfDay())))
    logger.Info("Start local time of time", zap.Int64("value", datetime.ConvertLocalTimeToMilliseconds(datetime.GetStartLocalTimeOfTime(time.Now()))))
    logger.Info("Start local time of time", zap.Int64("value", datetime.ConvertLocalTimeToMilliseconds(datetime.GetEndLocalTimeOfTime(time.Now()))))
    logger.Info("Get before local time of time", zap.Int64("value", datetime.ConvertLocalTimeToMilliseconds(datetime.GetBeforeLocalTimeOfTime(time.Now(), 9, true))))
    logger.Info("Get after local time of time", zap.Int64("value", datetime.ConvertLocalTimeToMilliseconds(datetime.GetAfterLocalTimeOfTime(time.Now(), 9, false))))
}
  • Detailed examples can be see here.
3.4 config
  • 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.
  • How to use?
  • Let's go.
func main() {
    logger.InitProduction("")
    serviceConfig := ServiceConfig{}

    // Load config from yaml file
    if err := config.Load(&serviceConfig, "dev.yaml"); err != nil {
        logger.Fatal("Failed to load config", zap.Error(err))
    }

    // We can provide path of config by flag to load config
    if err := config.LoadByFlag(&serviceConfig, "cfgPath"); err != nil {
        logger.Fatal("Failed to load config", zap.Error(err))
    }

    // Load config from json file
    if err := config.Load(&serviceConfig, "dev.json"); err != nil {
        logger.Fatal("Failed to load config", zap.Error(err))
    }

    // If you want omit hotkeys such as token, password,...
    if err := config.Print(serviceConfig, "Token", "Password"); err != nil {
        logger.Fatal("Failed to print config", zap.Error(err))
    }
}
  • Detailed examples can be see here.
3.5 conv
  • How to convert numbers and strings? How to convert string to number? It's simple because there's a convertor package.
  • I use strconv for conv package.
  • It includes the following data types: int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, bool.
  • How to use?
  • Don't go to google looking for ways to convert anymore.
func main() {
    logger.InitProduction("")

    numInt, err := conv.ConvertStringToInt("123456")
    if err != nil {
        logger.Fatal("Failed to convert string to int")
    }
    logger.Info("Convert string to int", zap.Int("Value", numInt))

    strInt := conv.ConvertIntToString(123456)
    logger.Info("Convert int to string", zap.String("Value", strUInt))
}
  • Detailed examples can be see here.
3.6 database
  • There are many libraries that support working with different databases.
  • Using the Database interface and you can implement datasource packages such as mysql, postgresql.
  • Example: I use sqlx to work with mysql and implement MySQLImpl struct.
  • How to use?
  • This is the most approachable I've ever done.
// AccountDTO data transfer object
type AccountDTO struct {
	ID          int64  `db:"id"`
	Username    string `db:"username"`
	Password    string `db:"password"`
	Email       string `db:"email"`
	Status      int    `db:"status"`
	Role        string `db:"role"`
	CreatedTime int64  `db:"created_time"`
	UpdatedTime int64  `db:"updated_time"`
}

func main() {
    logger.InitProduction("")

    config := database.MySQLConfig{
        User:                      "dbgtest",
        Password:                  "abc@123",
        Host:                      "10.30.17.173",
        Port:                      4000,
        DBName:                    "go_admin",
        PoolName:                  "account_da",
        PoolSize:                  10,
        MaxIdleConns:              2,
        ConnMaxLifetimeInMs:       10000,
        ReadTimeoutInMs:           3000,
        WriteTimeoutInMs:          3000,
        DialConnectionTimeoutInMs: 3000,
    }

    mysql, err := database.NewMySQLImpl(config)
    if err != nil {
        logger.Fatal("Failed to create mysql", zap.Error(err))
    }
    defer mysql.Disconnect()

    db := mysql.GetConnection().(*sqlx.DB)

    //
    // Insert new account into DB
    newAccount := AccountDTO{
        Username:    "AJPham",
        Password:    "123@ajpham",
        Email:       "go-util@gmail.com",
        Status:      1,
        Role:        "admin",
        CreatedTime: datetime.GetCurrentMiliseconds(),
        UpdatedTime: datetime.GetCurrentMiliseconds(),
    }

    resultInsert, err := db.Exec("INSERT INTO account (username, password, email, status, role, created_time, updated_time) VALUES (?, ?, ?, ?, ?, ?, ?)",
        newAccount.Username, newAccount.Password, newAccount.Email, newAccount.Status, newAccount.Role, newAccount.CreatedTime, newAccount.UpdatedTime)
    if err != nil {
        logger.Fatal("Failed to insert new account", zap.Error(err))
    }

    rowInserted, err := resultInsert.RowsAffected()
    if err != nil {
        logger.Fatal("Failed to insert new account", zap.Error(err))
    }
    logger.Info("Insert account successed", zap.Int64("Row affected", rowInserted))
  • Detailed examples can be see here.

Documentation

Overview

Package utils provides simple utils that help us quickly build projects. Currently, there are the following packages:

logger: Package provides a way to create global logger.

ero: Package provides a way to create error wrapper.

datetime: Package provides features for working with datetime

config: Package provides a way to load configuration from yaml and json files.

conv: Package provides a string and number converter.

database: Package database provides an interface Database that can be implemented by different data sources.

Directories

Path Synopsis
cmd
config
Package main contains examples of how to use the config package
Package main contains examples of how to use the config package
convertor
Package main contains examples of how to use the conv package
Package main contains examples of how to use the conv package
datetime
Package main contains examples of how to use the datetime package
Package main contains examples of how to use the datetime package
db
Package main contains examples of how to use the mysql of database package
Package main contains examples of how to use the mysql of database package
error
Package main contains examples of how to use the error package
Package main contains examples of how to use the error package
logger
Package main contains examples of how to use the logger package
Package main contains examples of how to use the logger package
utils
config
Package config provides a way to load configuration of application from yaml and json file.
Package config provides a way to load configuration of application from yaml and json file.
convertor
Package conv provides a string and number converter.
Package conv provides a string and number converter.
datetime
Package datetime provides a way to working with datetime.
Package datetime provides a way to working with datetime.
db
Package database provides an interface Database that can be implemented by different data sources.
Package database provides an interface Database that can be implemented by different data sources.
error
Package ero provides a way to create error wrapper.
Package ero provides a way to create error wrapper.
logger
Package logger provides a way to create global logger.
Package logger provides a way to create global logger.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL