LimitR / goresult

If you are tired of writing "if err != nil"

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

goresult

Install

go get github.com/LimitR/goresult

Using

package main

import (
	"github.com/LimitR/goresult"
)


func main() {
	c := goresult.NewResult("value ok")
	c2 := getResultOk()
	c3 := getResultError()
	fmt.Println(c.Unwrap()) // value ok
	fmt.Println(c2.Unwrap()) // ok
	fmt.Println(c3.Unwrap()) // 2022/08/14 16:25:47 Not ok
	fmt.Println(c3.Expect("Castom panic")) // panic: Castom panic

    file := goresult.CreateResultFrom(os.Open("/path/to/file.txt")).Unwrap()
	defer file.Close()
}

func getResultOk() *goresult.Result[string] {
	res := goresult.NewResult("ok")
	return res
}

func getResultError() *goresult.Result[string] {
	res := goresult.NewResult("ok")
	res.AddError(errors.New("Not ok"))
	return res
}

Check Error

c3 := getResultError()
	if !c3.IsOk() {
		c3 = goresult.NewResult("default")
	}
fmt.Println(c3.Unwrap()) // default

// Or

c3 := getResultError()

fmt.Println(c3.UnwrapOrElse("default")) // default

If the result is an error, the value will be deleted after processing

Error Handling

c3 := getResultError().UnwrapOrOn(func(res error) string {
	fmt.Println(res.Error()) // Not ok
	return "default" // new value c3
})
fmt.Println(c3) // default

// Or

c3 := getResultError().UnwrapDelay(func(res string) {
	fmt.Println(res) // ok - value Result
	// ... Some code before the panic
	// ...
}) // panic: AAAA

// Or

c3 := getResultError().UnwrapDelay(func(res string) {
	fmt.Println(res) // ok - value Result
	recover()
}) // not panic
// But c3 = Result[string]
fmt.Println(c3.Unwrap()) // ok

If you need to process more than one Result

c := goresult.NewResult("ok")
c2 := goresult.NewResult("ok2")
c2.AddError(errors.New("Panic"))
c3 := goresult.NewResult("ok3")

ch := []Result[string]{*c, *c2, *c3}

fmt.Println(goresult.CheckAll(ch)) // [ok ok3]

Trace error

func main() {
	result := a()
	value := result.Unwrap()
	fmt.Println(value)
}

func a() *goresult.Result[string] {
	result := b()
	// Some code...
	result.AddTrace()
	return result
}

func b() *goresult.Result[string] {
	result := c()
	// Some code...
	if !result.IsOk() {
		result.AddError(errors.New("Error in 'b'"))
	}
	return result
}

func c() *goresult.Result[string] {
	result := goresult.CreateResultFrom(d())
	// Some code...
	return result
}

func d() (string, error) {
	return "", errors.New("Error in 'd'")
}

Out:

panic:
Trace: main:12 -> a:19 -> b:27 -> c:33
Message: b 'Error in "b"', c 'Error in "d"'

Disable trace

// Some function
// ...
func c() *goresult.Result[string] {
	v, e := d()
	result := goresult.CreateResultFrom(v, e, false)
	// Some code...
	return result
}

func d() (string, error) {
	return "", errors.New("Error in 'd'")
}

Out:

panic: Error in 'b'

Output last error

Get trace

func main() {
	result := a()
	value := result.GetErrorTrace() // []trace
	fmt.Println(value[0].Message)  // Error in 'd'
	fmt.Println(value[0].FileName) // /home/.../main.go
	fmt.Println(value[0].FnName)   // c
	fmt.Println(value[0].Line)     // 37
}

Context

func main() {
	// Create context with timeout
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel()
	res := a(ctx)
	r := <-res
	result := r.Unwrap()
	fmt.Println(result) // Data
}

func a(ctx context.Context) chan *goresult.Result[string] {
	res := goresult.CreateResultChannel(ctx, d)
	return res
}

func d() (string, error) {
	time.Sleep(1 * time.Second)
	return "Data", nil
}

Or

func main() {
	// Create context with timeout
	ctx, cancel := context.WithTimeout(context.Background(), 0)
	defer cancel()
	res := a(ctx)
	r := <-res
	result := r.Unwrap() // Panic
	// Trace: main:16 -> a:21
	// Message: a 'context deadline exceeded'
	fmt.Println(result)
}

func a(ctx context.Context) chan *goresult.Result[string] {
	res := goresult.CreateResultChannel(ctx, d)
	return res
}

func d() (string, error) {
	time.Sleep(1 * time.Second)
	return "Data", nil
}

About

If you are tired of writing "if err != nil"


Languages

Language:Go 100.0%