1st
This commit is contained in:
commit
e8a06e8edd
3 changed files with 585 additions and 0 deletions
13
go.mod
Normal file
13
go.mod
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
module github.com/zeevdiukman/go-helper
|
||||||
|
|
||||||
|
go 1.24.0
|
||||||
|
|
||||||
|
require github.com/gookit/goutil v0.6.18
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gookit/color v1.5.4 // indirect
|
||||||
|
github.com/gorilla/mux v1.8.1
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
|
golang.org/x/sys v0.28.0 // indirect
|
||||||
|
golang.org/x/text v0.21.0 // indirect
|
||||||
|
)
|
||||||
22
go.sum
Normal file
22
go.sum
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
|
||||||
|
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
|
||||||
|
github.com/gookit/goutil v0.6.18 h1:MUVj0G16flubWT8zYVicIuisUiHdgirPAkmnfD2kKgw=
|
||||||
|
github.com/gookit/goutil v0.6.18/go.mod h1:AY/5sAwKe7Xck+mEbuxj0n/bc3qwrGNe3Oeulln7zBA=
|
||||||
|
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||||
|
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||||
|
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E=
|
||||||
|
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||||
|
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
550
helper.go
Normal file
550
helper.go
Normal file
|
|
@ -0,0 +1,550 @@
|
||||||
|
package helper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/tls"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"os/signal"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/gookit/goutil/dump"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
)
|
||||||
|
|
||||||
|
// const (
|
||||||
|
// COLOR_Reset = "\033[0m"
|
||||||
|
// COLOR_Red = "\033[31m"
|
||||||
|
// COLOR_Green = "\033[32m"
|
||||||
|
// COLOR_Yellow = "\033[33m"
|
||||||
|
// COLOR_Blue = "\033[34m"
|
||||||
|
// COLOR_Purple = "\033[35m"
|
||||||
|
// COLOR_Cyan = "\033[36m"
|
||||||
|
// COLOR_Gray = "\033[37m"
|
||||||
|
// COLOR_White = "\033[97m" // Brighter white
|
||||||
|
// )
|
||||||
|
|
||||||
|
// func Log(msg string) {
|
||||||
|
// log.New(os.Stdout, msg, log.Ldate|log.Ltime)
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func Colorize(colorCode string, message string) string {
|
||||||
|
// return colorCode + message + COLOR_Reset
|
||||||
|
// }
|
||||||
|
|
||||||
|
type IsStruct struct{}
|
||||||
|
|
||||||
|
var (
|
||||||
|
Is IsStruct
|
||||||
|
h = New()
|
||||||
|
)
|
||||||
|
|
||||||
|
type Helper struct {
|
||||||
|
Convert Convert
|
||||||
|
Struct Struct
|
||||||
|
Screen Screen
|
||||||
|
Error Error
|
||||||
|
If If
|
||||||
|
Log Log
|
||||||
|
}
|
||||||
|
type Convert struct {
|
||||||
|
}
|
||||||
|
type Struct struct {
|
||||||
|
}
|
||||||
|
type Screen struct {
|
||||||
|
}
|
||||||
|
type Error struct {
|
||||||
|
Val error
|
||||||
|
}
|
||||||
|
type If struct {
|
||||||
|
Error Error
|
||||||
|
}
|
||||||
|
type Log struct {
|
||||||
|
Error Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Helper) P(val any) {
|
||||||
|
dump.Println(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsertStringValueIntoField inserts a string value into a specified field of a struct.
|
||||||
|
//
|
||||||
|
// structPtr must be a pointer to a struct.
|
||||||
|
// fieldName is the name of the field (case-sensitive).
|
||||||
|
// stringValue is the string value to be inserted.
|
||||||
|
//
|
||||||
|
// Returns an error if:
|
||||||
|
// - structPtr is not a pointer to a struct.
|
||||||
|
// - The fieldName is not found in the struct.
|
||||||
|
// - The field is not settable (e.g., unexported).
|
||||||
|
// - The field is not of type string.
|
||||||
|
func New() *Helper {
|
||||||
|
return &Helper{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Error) Log() {
|
||||||
|
if e.Val != nil {
|
||||||
|
log.Println(e.Val.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (e *Error) In(err error) *Error {
|
||||||
|
e.Val = err
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
func (conv *Struct) Insert(structPtr interface{}, param ...any) {
|
||||||
|
// func (conv *Struct) Insert(structPtr interface{}, fieldName string, stringValue string, sep string) string {
|
||||||
|
|
||||||
|
rawFieldName := param[0].(string)
|
||||||
|
fieldValue := param[1]
|
||||||
|
sep := ""
|
||||||
|
if len(param) > 2 {
|
||||||
|
sep = param[2].(string)
|
||||||
|
} else {
|
||||||
|
sep = "_"
|
||||||
|
}
|
||||||
|
// if len(param[2].(string)) > 0 {
|
||||||
|
// sep = param[2].(string)
|
||||||
|
// }
|
||||||
|
seperatorRune := []rune(sep)[0]
|
||||||
|
field := CapitalizeAfterChar(rawFieldName, seperatorRune)
|
||||||
|
field = CapitalizeFirstLetter(field)
|
||||||
|
field = strings.ReplaceAll(field, sep, "")
|
||||||
|
|
||||||
|
err := InsertAnyValueIntoField(structPtr, field, fieldValue)
|
||||||
|
h.Error.Val = err
|
||||||
|
h.If.Error.Log()
|
||||||
|
}
|
||||||
|
func (conv *Struct) ToStructField(str string, seperator string) string {
|
||||||
|
seperatorRune := []rune(seperator)[0]
|
||||||
|
field := CapitalizeAfterChar(str, seperatorRune)
|
||||||
|
field = CapitalizeFirstLetter(field)
|
||||||
|
field = strings.ReplaceAll(field, seperator, "")
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
func InsertStringValueIntoField(structPtr interface{}, fieldName string, stringValue string) error {
|
||||||
|
if structPtr == nil {
|
||||||
|
return errors.New("structPtr cannot be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
val := reflect.ValueOf(structPtr)
|
||||||
|
if val.Kind() != reflect.Ptr {
|
||||||
|
return errors.New("structPtr must be a pointer to a struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
elem := val.Elem()
|
||||||
|
if elem.Kind() != reflect.Struct {
|
||||||
|
return errors.New("structPtr must be a pointer to a struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldVal := elem.FieldByName(fieldName)
|
||||||
|
if !fieldVal.IsValid() {
|
||||||
|
return fmt.Errorf("field '%s' not found in struct", fieldName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !fieldVal.CanSet() {
|
||||||
|
return fmt.Errorf("field '%s' is not settable (unexported or embedded without being exported)", fieldName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if fieldVal.Kind() != reflect.String {
|
||||||
|
return fmt.Errorf("field '%s' is not a string type", fieldName)
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldVal.SetString(stringValue)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func InsertAnyValueIntoField(structPtr interface{}, fieldName string, anyValue any) error {
|
||||||
|
if structPtr == nil {
|
||||||
|
return errors.New("structPtr cannot be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
val := reflect.ValueOf(structPtr)
|
||||||
|
if val.Kind() != reflect.Ptr {
|
||||||
|
return errors.New("structPtr must be a pointer to a struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
elem := val.Elem()
|
||||||
|
if elem.Kind() != reflect.Struct {
|
||||||
|
return errors.New("structPtr must be a pointer to a struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldVal := elem.FieldByName(fieldName)
|
||||||
|
if !fieldVal.IsValid() {
|
||||||
|
return fmt.Errorf("field '%s' not found in struct", fieldName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !fieldVal.CanSet() {
|
||||||
|
return fmt.Errorf("field '%s' is not settable (unexported or embedded without being exported)", fieldName)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v := anyValue.(type) {
|
||||||
|
case string:
|
||||||
|
{
|
||||||
|
if fieldVal.Kind() != reflect.String {
|
||||||
|
return fmt.Errorf("field '%s' is not a string type", fieldName)
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldVal.SetString(v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
case bool:
|
||||||
|
{
|
||||||
|
if fieldVal.Kind() != reflect.Bool {
|
||||||
|
return fmt.Errorf("field '%s' is not a string type", fieldName)
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldVal.SetBool(v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Errorf("value of field '%s' is unknown type", fieldName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CapitalizeAfterChar capitalizes the first letter immediately following each occurrence of a specific character in a string.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// CapitalizeAfterChar("hello_world", '_') == "hello_World"
|
||||||
|
// CapitalizeAfterChar("this-is-a-test", '-') == "this-Is-A-Test"
|
||||||
|
// CapitalizeAfterChar(" leading spaces and_underscores", '_') == " leading spaces and_Underscores"
|
||||||
|
func CapitalizeAfterChar(input string, char rune) string {
|
||||||
|
var result strings.Builder
|
||||||
|
capitalizeNext := false // Flag to indicate if the next letter should be capitalized
|
||||||
|
|
||||||
|
for _, r := range input {
|
||||||
|
if capitalizeNext {
|
||||||
|
result.WriteRune(unicode.ToUpper(r)) // Capitalize the current rune
|
||||||
|
capitalizeNext = false // Reset the flag
|
||||||
|
} else {
|
||||||
|
result.WriteRune(r) // Write the rune as is
|
||||||
|
}
|
||||||
|
|
||||||
|
if r == char {
|
||||||
|
capitalizeNext = true // Set the flag to capitalize the next letter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func CapitalizeAfterCharMulti(input string, char rune) string {
|
||||||
|
var result strings.Builder
|
||||||
|
capitalizeNext := false // Flag to indicate if the next letter should be capitalized
|
||||||
|
|
||||||
|
for _, r := range input {
|
||||||
|
if capitalizeNext {
|
||||||
|
result.WriteRune(unicode.ToUpper(r)) // Capitalize the current rune
|
||||||
|
capitalizeNext = false // Reset the flag
|
||||||
|
} else {
|
||||||
|
result.WriteRune(r) // Write the rune as is
|
||||||
|
}
|
||||||
|
|
||||||
|
if r == char {
|
||||||
|
capitalizeNext = true // Set the flag to capitalize the next letter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func CapitalizeFirstLetter(input string) string {
|
||||||
|
if input == "" {
|
||||||
|
return input // Return empty string if input is empty
|
||||||
|
}
|
||||||
|
|
||||||
|
runes := []rune(input) // Convert string to rune slice for Unicode support
|
||||||
|
firstRune := runes[0]
|
||||||
|
|
||||||
|
if !unicode.IsLetter(firstRune) {
|
||||||
|
return input // Return original string if first char is not a letter
|
||||||
|
}
|
||||||
|
|
||||||
|
capitalizedFirstRune := unicode.ToUpper(firstRune)
|
||||||
|
runes[0] = capitalizedFirstRune
|
||||||
|
|
||||||
|
return string(runes) // Convert rune slice back to string
|
||||||
|
}
|
||||||
|
func MapIter[K string, V any](m map[K]V, fn func(K, V)) {
|
||||||
|
for p, d := range m {
|
||||||
|
fn(p, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func Clear() {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
cmd := exec.Command("cmd", "/c", "cls")
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Run()
|
||||||
|
} else {
|
||||||
|
cmd := exec.Command("clear")
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandStringByBits(nBits int) string {
|
||||||
|
b := make([]byte, nBits/8)
|
||||||
|
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
return base64.RawURLEncoding.EncodeToString(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StructToMap(obj interface{}) map[string]any {
|
||||||
|
|
||||||
|
val := reflect.ValueOf(obj)
|
||||||
|
typ := reflect.TypeOf(obj)
|
||||||
|
result := make(map[string]any)
|
||||||
|
|
||||||
|
for i := 0; i < val.NumField(); i++ {
|
||||||
|
field := typ.Field(i)
|
||||||
|
result[field.Name] = val.Field(i).Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func FetchGetJson(u string) (map[string]any, error) {
|
||||||
|
resp, err := http.Get(u)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
respByes, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
data := map[string]any{}
|
||||||
|
json.Unmarshal(respByes, &data)
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLastChar(str string) string {
|
||||||
|
return str[len(str)-1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsLastChar(str string, chr string) bool {
|
||||||
|
if l := GetLastChar(str); l == chr {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsLastCharDo(str string, chr string, f func(r bool)) bool {
|
||||||
|
result := IsLastChar(str, chr)
|
||||||
|
|
||||||
|
func(bool) {
|
||||||
|
f(result)
|
||||||
|
}(result)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsFetchOK[V any](u string, funcName string, f func(string) (*http.Response, error)) *http.Response {
|
||||||
|
// errCntr := 0
|
||||||
|
errCntrTotal := 0
|
||||||
|
var (
|
||||||
|
a V
|
||||||
|
resp *http.Response
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
for {
|
||||||
|
resp, err = f(u)
|
||||||
|
if err == nil && resp.StatusCode == 200 {
|
||||||
|
// ClearScreen()
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
// errCntr++
|
||||||
|
// errCntrTotal++
|
||||||
|
// if errCntr == 10 {
|
||||||
|
// errCntr = 0
|
||||||
|
// ClearScreen()
|
||||||
|
// }
|
||||||
|
// if errCntr == 1 {
|
||||||
|
// ClearScreen()
|
||||||
|
// }
|
||||||
|
errCntrTotalStr := strconv.Itoa(errCntrTotal)
|
||||||
|
pkg := reflect.TypeOf(a).PkgPath()
|
||||||
|
dt := time.Now()
|
||||||
|
dateTime := dt.Format("02-01-2006 15:04:05")
|
||||||
|
fmt.Println("ERROR: " + dateTime + ">---------<" + errCntrTotalStr + ">")
|
||||||
|
fmt.Println(" :")
|
||||||
|
fmt.Println(" Package name: " + pkg)
|
||||||
|
fmt.Println("Function name: " + funcName)
|
||||||
|
fmt.Println(" URL: " + u)
|
||||||
|
fmt.Println("Error message: " + err.Error())
|
||||||
|
fmt.Println("--------------------------------------")
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsSliceContains[T comparable](sliceVals []T, valueToSearch T) bool {
|
||||||
|
for _, v := range sliceVals {
|
||||||
|
if v == valueToSearch {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddDotBetween(k ...string) string {
|
||||||
|
constructedKey := ""
|
||||||
|
for i, key := range k {
|
||||||
|
constructedKey += key
|
||||||
|
if i < len(k)-1 {
|
||||||
|
constructedKey += "."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return constructedKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveSliceDuplicates(elements []string) []string {
|
||||||
|
encountered := map[string]bool{}
|
||||||
|
result := []string{}
|
||||||
|
|
||||||
|
for v := range elements {
|
||||||
|
if encountered[elements[v]] {
|
||||||
|
// Do not add duplicate.
|
||||||
|
} else {
|
||||||
|
// Record this element as an encountered element.
|
||||||
|
encountered[elements[v]] = true
|
||||||
|
// Append to result slice.
|
||||||
|
result = append(result, elements[v])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Return the new slice.
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func IfLast[T any](counter int, someVar map[string]T, fn func()) {
|
||||||
|
counter++
|
||||||
|
if len(someVar) == counter {
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IsStruct) Pointer(v any) bool {
|
||||||
|
|
||||||
|
valueOfP := reflect.ValueOf(v)
|
||||||
|
if valueOfP.Kind() == reflect.Ptr {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AppRunner(shoudClear bool, runApp func()) {
|
||||||
|
|
||||||
|
if shoudClear {
|
||||||
|
Clear()
|
||||||
|
}
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
v := recover()
|
||||||
|
fmt.Println("Recovered:", v)
|
||||||
|
}()
|
||||||
|
|
||||||
|
runApp()
|
||||||
|
|
||||||
|
<-ctx.Done()
|
||||||
|
//do stuff after ending
|
||||||
|
wg.Wait()
|
||||||
|
log.Println("AppRunner stopped")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartTestHTTPServer(port int, name string) {
|
||||||
|
p := strconv.Itoa(port)
|
||||||
|
go func() {
|
||||||
|
fmt.Println("Test server (" + name + "): listening port " + p)
|
||||||
|
// fmt.Println("Test server is running at http://" + GetIP() + ":" + p)
|
||||||
|
r := mux.NewRouter()
|
||||||
|
r.Path("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Fprintln(w, r.Host+"/ OK")
|
||||||
|
})
|
||||||
|
r.Path("/test1").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Fprintln(w, r.Host+"/test1 OK")
|
||||||
|
})
|
||||||
|
r.Path("/test2").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Fprintln(w, r.Host+"/test2 OK")
|
||||||
|
})
|
||||||
|
err := http.ListenAndServe(":"+p, r)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIP(prefix ...string) string {
|
||||||
|
prfx := "192.168."
|
||||||
|
if len(prefix) > 0 {
|
||||||
|
prfx = prefix[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs, err := net.InterfaceAddrs()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error getting interface addresses:", err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
// Check if the address is an IP address
|
||||||
|
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||||
|
|
||||||
|
a := strings.HasPrefix(ipnet.IP.String(), prfx)
|
||||||
|
c := ipnet.IP.To4() != nil
|
||||||
|
if c && a { //check for ipv4
|
||||||
|
prfx = ipnet.IP.String()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// } else if ipnet.IP.To16() != nil { //check for ipv6
|
||||||
|
// fmt.Println("Local IPv6 address:", ipnet.IP.String())
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prfx
|
||||||
|
}
|
||||||
|
|
||||||
|
func AppendToPointer[T any](slc *[]T, val T) {
|
||||||
|
*slc = append(*slc, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadCertificate(certFile, keyFile string) (tls.Certificate, error) {
|
||||||
|
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
||||||
|
if err != nil {
|
||||||
|
return tls.Certificate{}, err
|
||||||
|
}
|
||||||
|
return cert, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsStringEmpty(str string) bool {
|
||||||
|
return str == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsKeyExistsInMap[V comparable](mp map[string]V, key string) (V, bool, error) {
|
||||||
|
if val, ok := mp[key]; !ok {
|
||||||
|
err := errors.New("Error: missing \"" + key + "\" key")
|
||||||
|
log.Println(err.Error())
|
||||||
|
return val, ok, err
|
||||||
|
} else {
|
||||||
|
return val, ok, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue