diff --git a/.golangci.yml b/.golangci.yml index 54cda6a..6a68b00 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -53,7 +53,6 @@ linters: - inamedparam # reports interfaces with unnamed method parameters - interfacebloat # check for large interfaces - intrange # find places where for loops could make use of an integer range - - ireturn # Accept Interfaces, Return Concrete Types. - lll # check for long lines - maintidx # measures the maintainability index of each function - mirror # reports wrong mirror patterns of bytes/strings usage @@ -123,6 +122,7 @@ linters: - mnd # too many detections - cyclop # covered by gocyclo - gochecknoglobals # there are many valid reasons for global variables, depending on the project + - ireturn # there are too many exceptions linters-settings: wsl: @@ -139,6 +139,9 @@ linters-settings: line-length: 140 tab-width: 1 + nlreturn: + block-size: 2 + exhaustive: check-generated: false default-signifies-exhaustive: true diff --git a/file.go b/file.go index a9a266e..61a919e 100644 --- a/file.go +++ b/file.go @@ -11,28 +11,34 @@ import ( func ReadFile(path string) (string, error) { res, err := os.ReadFile(path) if err != nil { - return "", err + return "", fmt.Errorf("could not read file: %w", err) } + return string(res), nil } // WriteFile writes the given content to the given file. // Accepts a string or a byte slice. func WriteFile[T string | []byte](path string, content T) error { - return os.WriteFile(path, []byte(content), 0644) + err := os.WriteFile(path, []byte(content), 0o600) + if err != nil { + return fmt.Errorf("could not write file: %w", err) + } + + return nil } // AppendToFile appends the given content to the given file. // Accepts a string or a byte slice. func AppendToFile[T string | []byte](path string, content T) error { - f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0644) + file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0o600) if err != nil { - return err + return fmt.Errorf("could not open file: %w", err) } - defer f.Close() + defer file.Close() - if _, err = f.Write([]byte(content)); err != nil { - return err + if _, err = file.Write([]byte(content)); err != nil { + return fmt.Errorf("could not write to file: %w", err) } return nil @@ -49,23 +55,23 @@ func FileExists(path string) bool { func DownloadFile(url, path string) error { out, err := os.Create(path) if err != nil { - return err + return fmt.Errorf("could not create file: %w", err) } defer out.Close() - resp, err := http.Get(url) + resp, err := http.Get(url) //nolint:gosec // wrapper function if err != nil { - return err + return fmt.Errorf("could not download file: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - return fmt.Errorf("bad status: %s", resp.Status) + return fmt.Errorf("bad status: %s", resp.Status) //nolint: err113 } _, err = io.Copy(out, resp.Body) if err != nil { - return err + return fmt.Errorf("could not write file: %w", err) } return nil diff --git a/to.go b/to.go index ae64472..9d2e66d 100644 --- a/to.go +++ b/to.go @@ -1,19 +1,21 @@ package utils import ( - "atomicgo.dev/constraints" "encoding/json" "fmt" "strconv" "strings" + + "atomicgo.dev/constraints" ) // ToJSON converts the given value to a JSON string. func ToJSON(v any) (string, error) { r, err := json.Marshal(v) if err != nil { - return "", err + return "", fmt.Errorf("could not marshal json: %w", err) } + return string(r), nil } @@ -24,8 +26,9 @@ func ToPrettyJSON(v any, indent ...string) (string, error) { r, err := json.MarshalIndent(v, "", indent[0]) if err != nil { - return "", err + return "", fmt.Errorf("could not marshal json: %w", err) } + return string(r), nil } @@ -36,46 +39,47 @@ func ToString(v any) string { // ToInt converts the given value to an int. // If the value is a float, it will be rounded to the nearest integer. (Rounds up if the decimal is 0.5 or higher) -func ToInt[T string | constraints.Number](v T) int { - switch v := any(v).(type) { +func ToInt[T string | constraints.Number](value T) int { + switch value := any(value).(type) { case int: - return v + return value case int8: - return int(v) + return int(value) case int16: - return int(v) + return int(value) case int32: - return int(v) + return int(value) case int64: - return int(v) + return int(value) case uint: - return int(v) + return int(value) case uint8: - return int(v) + return int(value) case uint16: - return int(v) + return int(value) case uint32: - return int(v) + return int(value) case uint64: - return int(v) + return int(value) case float32: - v += 0.5 - return int(v) + value += 0.5 + return int(value) case float64: - v += 0.5 - return int(v) + value += 0.5 + return int(value) case string: var i int - if !strings.Contains(v, ".") { - i, _ = strconv.Atoi(v) + if !strings.Contains(value, ".") { + i, _ = strconv.Atoi(value) } else { - f, _ := strconv.ParseFloat(v, 64) + f, _ := strconv.ParseFloat(value, 64) f += 0.5 // Round up i = int(f) } return i + default: return 0 } diff --git a/to_test.go b/to_test.go index 7b6971f..f9138fd 100644 --- a/to_test.go +++ b/to_test.go @@ -1,8 +1,9 @@ package utils_test import ( - "atomicgo.dev/utils" "fmt" + + "atomicgo.dev/utils" ) type Person struct { @@ -11,7 +12,7 @@ type Person struct { } func ExampleToJSON() { - var person = Person{"John Doe", 42} + person := Person{"John Doe", 42} json, _ := utils.ToJSON(person) fmt.Println(json) @@ -52,8 +53,8 @@ func ExampleToString() { func ExampleToPrettyJSON() { person := Person{Name: "John Doe", Age: 42} - prettyJson, _ := utils.ToPrettyJSON(person) - fmt.Println(prettyJson) + prettyJSON, _ := utils.ToPrettyJSON(person) + fmt.Println(prettyJSON) // Output: // { diff --git a/utils.go b/utils.go index 32e3b23..1c0e7be 100644 --- a/utils.go +++ b/utils.go @@ -3,6 +3,7 @@ package utils import ( "bytes" "encoding/json" + "fmt" "net/http" ) @@ -12,6 +13,7 @@ func Ternary[T any](condition bool, a, b T) T { if condition { return a } + return b } @@ -19,30 +21,33 @@ func Ternary[T any](condition bool, a, b T) T { // If indent is not provided, it defaults to " " (two spaces). func PrettyJSON(inputJSON string, indent ...string) (string, error) { var out bytes.Buffer + if len(indent) == 0 { indent = append(indent, " ") } err := json.Indent(&out, []byte(inputJSON), "", indent[0]) if err != nil { - return "", err + return "", fmt.Errorf("failed to pretty-print JSON: %w", err) } + return out.String(), nil } // Fetch returns the body of a GET request to the given URL. func Fetch(url string) (string, error) { - resp, err := http.Get(url) + resp, err := http.Get(url) //nolint: gosec if err != nil { - return "", err + return "", fmt.Errorf("failed to fetch URL: %w", err) } defer resp.Body.Close() var buf bytes.Buffer + _, err = buf.ReadFrom(resp.Body) if err != nil { - return "", err + return "", fmt.Errorf("failed to read response body: %w", err) } return buf.String(), nil diff --git a/utils_test.go b/utils_test.go index 6818ef1..9ecbfce 100644 --- a/utils_test.go +++ b/utils_test.go @@ -1,8 +1,9 @@ package utils_test import ( - "atomicgo.dev/utils" "fmt" + + "atomicgo.dev/utils" ) func ExampleTernary() { @@ -17,8 +18,8 @@ func ExampleTernary() { func ExamplePrettyJSON() { person := Person{Name: "John Doe", Age: 42} json, _ := utils.ToJSON(person) - prettyJson, _ := utils.PrettyJSON(json) - fmt.Println(prettyJson) + prettyJSON, _ := utils.PrettyJSON(json) + fmt.Println(prettyJSON) // Output: // {