shorterr

package module
v0.0.0-...-62db747 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2023 License: MIT Imports: 3 Imported by: 0

README

shorterr

Go Report Card GoDoc

Introduction

This is a simple library that implements short-circuit style error handling, similar to the ? operator in Rust. That is, in case of errors or other failures, the current function is interrupted and the error is returned.

Usage

A function that wants to use shorterr must install the PassTo function with a defer, and then make use of the various check and wrapper functions, provided for different function signatures.

Code that originally looks like this

func myFunc() (string, error) {
	file, err := os.Open("data.json")
	if err != nil {
		return "", err
	}

	jsonData, err := io.ReadAll(file)
	if err != nil {
		return "", fmt.Errorf("can't read data.json: %w", err)
	}

	var myData map[string]any
	json.Unmarshal(jsonData, &myData)
	if err != nil {
		return "", fmt.Errorf("unmarshalling failed: %w", err)
	}

	val, ok := myData["name"]
	if !ok {
		return "", fmt.Errorf("missing name property")
	}

	name, ok := val.(string)
	if !ok {
		return "", fmt.Errorf("invalid name property")
	}

	return name, nil
}

can instead be written like this

...

import se "github.com/ansiwen/shorterr"

...

func myFunc() (name string, err error) {
	defer se.PassTo(&err)

	file := se.Try(os.Open("data.json"))

	jsonData := se.Do(io.ReadAll(file)).Or("can't read data.json")

	var myData map[string]any
	se.Check(json.Unmarshal(jsonData, &myData), "unmarshalling failed")

	val, ok := myData["name"]
	se.Assert(ok, "missing name property")

	name, ok = val.(string)
	se.Assert(ok, "invalid name property")

	return
}

Documentation

Overview

Package shorterr is an implementation of a short-circuit error handling inspired by the ? operator in Rust.

Example
package main

import (
	"encoding/json"
	"fmt"
	"io"
	"os"

	se "github.com/ansiwen/shorterr"
)

func main() {
	f1 := func() (string, error) {
		file, err := os.Open("data.json")
		if err != nil {
			return "", err
		}

		jsonData, err := io.ReadAll(file)
		if err != nil {
			return "", fmt.Errorf("can't read data.json: %w", err)
		}

		var myData map[string]any
		json.Unmarshal(jsonData, &myData)
		if err != nil {
			return "", fmt.Errorf("unmarshalling failed: %w", err)
		}

		val, ok := myData["name"]
		if !ok {
			return "", fmt.Errorf("missing name property")
		}

		name, ok := val.(string)
		if !ok {
			return "", fmt.Errorf("invalid name property")
		}

		return name, nil
	}

	f2 := func() (name string, err error) {
		defer se.PassTo(&err)

		file := se.Try(os.Open("data.json"))

		jsonData := se.Do(io.ReadAll(file)).Or("can't read data.json")

		var myData map[string]any
		se.Check(json.Unmarshal(jsonData, &myData), "unmarshalling failed")

		val, ok := myData["name"]
		se.Assert(ok, "missing name property")

		name, ok = val.(string)
		se.Assert(ok, "invalid name property")

		return
	}

	_, err1 := f1()
	_, err2 := f2()
	fmt.Println(err1)
	fmt.Println(err2)

}
Output:

open data.json: no such file or directory
open data.json: no such file or directory

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Assert

func Assert(ok bool, msg string)

Assert short-circuits the execution of the current function if ok is false and returns msg as an error. PassTo must be installed with defer before.

func Check

func Check(err error, msg ...string)

Check short-circuits the execution of the current function if the error is not nil. If the optional msg is provided, the err is wrapped with msg. PassTo must be installed with defer before.

func PassTo

func PassTo(err *error)

PassTo stores the intercepted error in the variable err is pointing to. It must be installed with defer in the current function before the other short-circuit functions are used:

import se "github.com/ansiwen/shorterr"

func Foo() (err error) {
	defer se.PassTo(&err)
...

func Try

func Try[A any](a A, err error) A

Try is a wrapper for functions that return a value and an error. It short-circuits the execution of the current function if the error is not nil. Otherwise it only returns the result value. PassTo must be installed with defer before.

func Try2

func Try2[A, B any](a A, b B, err error) (A, B)

Try2 is Try for functions with 2-ary results.

func Try3

func Try3[A, B, C any](a A, b B, c C, err error) (A, B, C)

Try3 is Try for functions with 3-ary results.

func Try4

func Try4[A, B, C, D any](a A, b B, c C, d D, err error) (A, B, C, D)

Try4 is Try for functions with 4-ary results.

func Try5

func Try5[A, B, C, D, E any](a A, b B, c C, d D, e E, err error) (A, B, C, D, E)

Try5 is Try for functions with 5-ary results.

Types

type Result

type Result[A any] struct {
	// contains filtered or unexported fields
}

func Do

func Do[A any](a A, err error) *Result[A]

Do is an alternative to Try that allows to wrap the short-circuit error with a description by appending the Or() method.

func (*Result[A]) Or

func (r *Result[A]) Or(msg string) A

Or returns only the result value of the function called by Do if its returned error is nil. Otherwise it wraps the error with msg and short-circuits the execution of the current function. PassTo must be installed with defer before.

type Result2

type Result2[A, B any] struct {
	// contains filtered or unexported fields
}

func Do2

func Do2[A, B any](a A, b B, err error) *Result2[A, B]

Do2 is Do for 2-ary results.

func (*Result2[A, B]) Or

func (r *Result2[A, B]) Or(msg string) (A, B)

Or for 2-ary results.

type Result3

type Result3[A, B, C any] struct {
	// contains filtered or unexported fields
}

func Do3

func Do3[A, B, C any](a A, b B, c C, err error) *Result3[A, B, C]

Do3 is Do for 3-ary results.

func (*Result3[A, B, C]) Or

func (r *Result3[A, B, C]) Or(msg string) (A, B, C)

Or for 3-ary results.

type Result4

type Result4[A, B, C, D any] struct {
	// contains filtered or unexported fields
}

func Do4

func Do4[A, B, C, D any](a A, b B, c C, d D, err error) *Result4[A, B, C, D]

Do4 is Do for 4-ary results.

func (*Result4[A, B, C, D]) Or

func (r *Result4[A, B, C, D]) Or(msg string) (A, B, C, D)

Or for 4-ary results.

type Result5

type Result5[A, B, C, D, E any] struct {
	// contains filtered or unexported fields
}

func Do5

func Do5[A, B, C, D, E any](a A, b B, c C, d D, e E, err error) *Result5[A, B, C, D, E]

Do5 is Do for 5-ary results.

func (*Result5[A, B, C, D, E]) Or

func (r *Result5[A, B, C, D, E]) Or(msg string) (A, B, C, D, E)

Or for 5-ary results.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL