github.com/packtpublishing/learning-functional-programming-in-go@v0.0.0-20230130084745-8b849f6d58c4/Chapter06/04_onion/src/utils/utils.go (about) 1 package utils 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "net/http" 8 "os" 9 "path" 10 "runtime" 11 "time" 12 "strings" 13 ) 14 15 type APIError struct { 16 ErrorMessage string `json:"error_message"` 17 HTTPStatus int `json:"http_status"` 18 } 19 20 type HttpErrorHandler struct { 21 Caller string 22 Response http.ResponseWriter 23 Request *http.Request 24 } 25 26 const ( 27 ErrorActionErr = iota 28 ErrorActionWarn 29 ErrorActionDebug 30 ErrorActionInfo 31 ) 32 33 func NewHttpErrorHandle(caller string, response http.ResponseWriter, request *http.Request) *HttpErrorHandler { 34 return &HttpErrorHandler{caller, response, request} 35 } 36 37 // HandleError locally, according to the action passed to h.Handle, and then serialized 38 // in json and sent to the remote address via http, then returns true. 39 // Otherwise, if there is no error, h.Handle returns false 40 func (h *HttpErrorHandler) Handle(err error, httpStatus int, action int) bool { 41 if err != nil { 42 _, filepath, line, _ := runtime.Caller(1) 43 _, file := path.Split(filepath) 44 Error.Printf("HttpErrorHandler()->[file:%s line:%d]: %s", file, line, err.Error()) 45 apiErr := &APIError{ 46 ErrorMessage: err.Error(), 47 HTTPStatus: httpStatus, 48 } 49 serialErr, _ := json.Marshal(&apiErr) 50 h.Response.Header().Set("Content-Type", "application/json") 51 h.Response.WriteHeader(httpStatus) 52 io.WriteString(h.Response, string(serialErr)) 53 } 54 return (err != nil) 55 } 56 57 // HandlePanic _Never_ returns on error, instead it panics 58 func FromLineOfFile() string { 59 _, filepath, line, _ := runtime.Caller(1) 60 _, file := path.Split(filepath) 61 return fmt.Sprintf("[file:%s line:%d]", file, line) 62 } 63 64 // HandlePanic _Never_ returns an error, instead it panics 65 func HandlePanic(err error) { 66 if err != nil { 67 _, filePath, lineNo, _ := runtime.Caller(1) 68 _, fileName := path.Split(filePath) 69 msg := fmt.Sprintf("[file:%s line:%d]: %s", fileName, lineNo, err.Error()) 70 panic(msg) 71 } 72 } 73 74 func HandleError(err error, action int) bool { 75 if err != nil { 76 _, filepath, line, _ := runtime.Caller(1) 77 _, file := path.Split(filepath) 78 switch action { 79 case ErrorActionErr: 80 Error.Printf("[file:%s line:%d]: %s", file, line, err.Error()) 81 break 82 case ErrorActionWarn: 83 Error.Printf("[file:%s line:%d]: %s", file, line, err.Error()) 84 break 85 case ErrorActionDebug: 86 Error.Printf("[file:%s line:%d]: %s", file, line, err.Error()) 87 break 88 case ErrorActionInfo: 89 Error.Printf("[file:%s line:%d]: %s", file, line, err.Error()) 90 break 91 } 92 } 93 return (err != nil) 94 } 95 96 func WriteFile(filename string, source io.Reader) error { 97 writer, err := os.Create(filename) 98 if err != nil { 99 return err 100 } 101 defer writer.Close() 102 io.Copy(writer, source) 103 return nil 104 } 105 106 // This is neat: https://coderwall.com/p/cp5fya/measuring-execution-time-in-go 107 func TimeTrack(start time.Time, name string) { 108 if Config.LogTimeTrack == true { 109 elapsed := time.Since(start) 110 Info.Printf("%s took %s", name, elapsed) 111 } 112 } 113 114 // pad str with padWith count times to right 115 func PadRight(str string, padWith string, length int) string { 116 count := length - len(str) 117 if count < 0 { 118 count = 0 119 } 120 return str + strings.Repeat(padWith, count) 121 } 122 123 func InSlice(slice []string, searchFor string) (found bool) { 124 for _, v := range slice { 125 if searchFor == v { 126 found = true 127 } 128 } 129 return found 130 }