<repo_name>ppp225/go-common<file_sep>/encoding.go
package common

import (
	"bytes"
	"encoding/gob"
	"fmt"
)

// ToGob - go binary encoder
func ToGob(m interface{}) []byte {
	b := bytes.Buffer{}
	e := gob.NewEncoder(&b)
	err := e.Encode(m)
	if err != nil {
		fmt.Println(`failed gob Encode`, err)
	}
	return b.Bytes()
}

// FromGob - go binary decoder
func FromGob(by []byte, m interface{}) {
	b := bytes.Buffer{}
	b.Write(by)
	d := gob.NewDecoder(&b)
	err := d.Decode(m)
	if err != nil {
		fmt.Println(`failed gob Decode`, err)
	}
}
<file_sep>/common.go
package common

import (
	"encoding/json"
	"fmt"
	"log"
	"regexp"
	"runtime"
	"time"
)

// Check check for error and panics, if not nil
func Check(e error) {
	if e != nil {
		panic(e)
	}
}

// Log writes to stdout if shoudLog flag is true
func Log(shoudLog bool, format string, a ...interface{}) {
	if shoudLog {
		fmt.Printf(format, a...)
	}
}

// ErrorTraced mimics panic() output.
//
// Usage: return ErrorTraced(err, inputAgrs...)
func ErrorTraced(prev error, args ...string) error {
	pc := make([]uintptr, 15)
	n := runtime.Callers(2, pc)
	frames := runtime.CallersFrames(pc[:n])
	frame, _ := frames.Next()
	return fmt.Errorf("%s(%v)\n\t%s:%d\n%s", frame.Function, args, frame.File, frame.Line, prev)
	//log.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
}

// Trace logs current code line trace
func Trace() {
	pc := make([]uintptr, 15)
	n := runtime.Callers(2, pc)
	frames := runtime.CallersFrames(pc[:n])
	frame, _ := frames.Next()
	log.Printf("%s,:%d %s\n", frame.File, frame.Line, frame.Function)
}

// CheckEmail checks e-mail format correctness
func CheckEmail(email string) (ok bool) {
	reEmail := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
	return reEmail.MatchString(email)
}

// ElapsedMs returns elapsed time between now and arg as ms
func ElapsedMs(start time.Time) float64 {
	return (float64)(time.Now().Sub(start).Nanoseconds()) / 1e6
}

// PrettyPrint prints objects prettier
func PrettyPrint(v interface{}) (err error) {
	b, err := json.MarshalIndent(v, "", "  ")
	if err == nil {
		fmt.Println(string(b))
	}
	return
}

// TODO: add retry function https://stackoverflow.com/questions/47606761/repeat-code-if-an-error-occured
<file_sep>/timeRemainingTimer.go
package common

import (
	"fmt"
	"log"
	"time"
)

// TimeRemainingTimer used to track progress
type TimeRemainingTimer struct {
	start     int64
	end       int64
	startTime int64
}

// CreateTimeRemainingTimer creates timer, that will interpolate remaining time based on some start & end indexes
func CreateTimeRemainingTimer(start, end int64) *TimeRemainingTimer {
	return &TimeRemainingTimer{
		start,
		end,
		time.Now().UnixNano(),
	}
}

// Start starts the timer
func (v *TimeRemainingTimer) Start() {
	v.startTime = time.Now().UnixNano()
}

// Restart restarts the timer with new start & end values
func (v *TimeRemainingTimer) Restart(start, end int64) {
	v.start = start
	v.end = end
	v.startTime = time.Now().UnixNano()
}

// Get returns %done & remainingTime for current index
func (v *TimeRemainingTimer) Get(current int64) (percentageDone float64, timeRemaining time.Duration) {
	now := time.Now().UnixNano()
	elapsed := now - v.startTime

	done := current - v.start
	total := v.end - v.start

	resultPerc := float64(done) / float64(total)
	remainingTime := int64(0)
	if resultPerc != 0 {
		remainingTime = int64(float64(elapsed)/resultPerc - float64(elapsed))
	}
	resultRemainingTime := time.Duration(remainingTime)

	return resultPerc, resultRemainingTime
}

// Getf returns formatted string of %done & remaining time
func (v *TimeRemainingTimer) Getf(current int64) string {
	p, r := v.Get(current)
	return fmt.Sprintf("Perc: %5.2f | Rem: %s", p*100, r.Round(time.Millisecond*10))
}

// Printr fmt.Printf's formatted %done & remaining time
func (v *TimeRemainingTimer) Printr(current int64) {
	p, r := v.Get(current)
	fmt.Printf("\rPerc: %5.2f | Rem: %s |     ", p*100, r.Round(time.Millisecond*10))
}

/////////////////////////////////////////////////////////////////////////

// TimeTrack logs elapsed time for task
func TimeTrack(start time.Time, name string) {
	elapsed := time.Since(start)
	log.Printf("%s took %s", name, elapsed.Round(time.Millisecond*10))
}
