util.go

// Execute f() n times on fail
func RetryHandler(n int, f func() (bool, error)) error {
	ok, er := f()
	if ok && er == nil {
		return nil
	}
	if n-1 > 0 {
		return RetryHandler(n-1, f)
	}
	return er
}

// Execute f() n times on fail, each time on fail will keep specific interval in order of `secondIntervals`
// If n < 0, it will forever execute f(), interval will used in order of `secondIntervals` and keep using the last interval element at last.
// Work in serial.
func RetryHandlerWithInterval(n int, f func() (bool, error), secondIntervals ... int) error {
	var offset = 0
	var ok bool
	var e error
	return retryHandlerWithIntervalOffset(&ok, &e, n, f, &offset, secondIntervals...)
}

// sub function of RetryHandlerWithInterval
func retryHandlerWithIntervalOffset(ok *bool, e *error, n int, f func() (bool, error), offset *int, secondIntervals ... int) error {
	if n == 0 {
		return nil
	}
	*ok, *e = f()
	if *ok && *e == nil {
		return nil
	}

	if n-1 > 0 && !(n < 0) {
		if *offset < len(secondIntervals) {
			time.Sleep(time.Duration(secondIntervals[*offset]) * time.Second)
			if *offset < len(secondIntervals)-1 {
				*offset ++
			}
		}
		return retryHandlerWithIntervalOffset(ok, e, n-1, f, offset, secondIntervals...)
	} else {
		if n != 1 {
			if *offset < len(secondIntervals) {
				time.Sleep(time.Duration(secondIntervals[*offset]) * time.Second)
				if *offset < len(secondIntervals)-1 {
					*offset ++
				}
			}
			return retryHandlerWithIntervalOffset(ok, e, n, f, offset, secondIntervals...)
		}
	}
	return *e
}

// Generate random string 32 bit
func RandomString() string {
	str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	var r *rand.Rand
	var once = sync.Once{}
	once.Do(func() {
		r = rand.New(rand.NewSource(time.Now().UnixNano()))
	})
	var result string
	for i := 0; i < 32; i++ {
		result += string(str[r.Intn(len(str))])
	}
	return result
}
// MD5 encrypt returning upper case 
func MD5(rawMsg string) string {
	data := []byte(rawMsg)
	has := md5.Sum(data)
	md5str1 := fmt.Sprintf("%x", has)
	return strings.ToUpper(md5str1)
}

// Returns well format output in json
func Debug(src interface{}) string {
	buf, e := json.MarshalIndent(src, "  ", "  ")
	if e != nil {
		fmt.Println(errorx.Wrap(e).Error())
	}
	return string(buf)
}