nexus

package module
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Feb 14, 2024 License: MIT Imports: 4 Imported by: 13

README

Build Status codecov Maintainability

nexus - package implements functions using nexus pattern

Primary use of nexus pattern is in error handling.

Quick start

go get github.com/gregoryv/nexus

func RenderSomething(w io.Writer) error {
    p, err := nexus.NewPrinter(os.Stdout)
    p.Print("My long")
    p.Println("text")
    p.Printf("Hello, %s", "World")
    return *err
}

Documentation

Overview

Package nexus focuses on simplifying error checking in go software.

Definition of the word 'nexus', according to WordNet

n 1: the means of connection between things linked in series
     [syn: {link}, {nexus}]
2: a connected series or group

Examples

When writing multiple values sequentially and you want to stop at the first error.

p, err := nexus.NewPrinter(os.Stdout)
p.Print("My long")
p.Println("text")
p.Printf("Hello, %s", "World")
return *err

Or a more complex sequence of steps

var (
  src  = "input.txt"
  dst  = "output.txt"
  in   *os.File
  out  *os.File
  err  error
  next = NewStepper(&err)
)

next.Step(func() {
  in, err = os.Open(src)
})

next.Stepf("create: %w", func() {
  out, err = os.Create(dst)
})

next.Stepf("copy: %w", func() {
  _, err = io.Copy(out, in)
})

One go idiom is to return the result of a function together with an error if one occured. It's a powerful idiom and works in most cases. When you are working with sequential flows however, the idiom is less suitable. You end up disrupting the flow with multiple error checks.

Redesign your funcs to only return an error and supply the result holder as an argument, ie.

func double(result *int, v int) error {...}
func toString(result *string, v int) error {...}
func concat(result *string, a,b string) error {...}

and then use

var (
   a = 1
   b = 3
   da, db int
   as, bs string
   result string
)
err := nexus.First(
   double(&da, a),
   double(&db, b),
   toString(&as, da),
   toString(&bs, db),
   concat(&result, as, bs),
)

The downside being that each step is actually executed. No silver bullet here either.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func First

func First(errors ...error) error

First returns the first error of the given ones or nil

Types

type Failure

type Failure struct {
	// contains filtered or unexported fields
}

func (*Failure) Error

func (me *Failure) Error() error

Error returns the failure error or nil if not set

func (*Failure) Fail

func (me *Failure) Fail(err error) error

Fail sets the given error unless already failed. An error can only be set once.

func (*Failure) Ok

func (me *Failure) Ok() bool

Ok return true if no error is set.

type Printer

type Printer struct {

	// Total number of bytes written
	Written int64
	// contains filtered or unexported fields
}

func NewPrinter

func NewPrinter(w io.Writer) (*Printer, *error)

NewPrinter returns a writer nexus. The referenced error is set by all methods if an error occurs.

Example
w, err := NewPrinter(os.Stdout)
w.Print("hello")
*err = fmt.Errorf("stop subsequent calls")
w.Printf("cruel %s", "world")
Output:

hello

func (*Printer) Print

func (t *Printer) Print(args ...interface{})

Print prints arguments using the underlying writer. Does nothing if Printer has failed.

func (*Printer) Printf

func (t *Printer) Printf(format string, args ...interface{})

Printf prints a formated string using the underlying writer. Does nothing if Printer has failed.

func (*Printer) Println

func (t *Printer) Println(args ...interface{})

Println prints arguments using the underlying writer. Does nothing if Printer has failed.

func (*Printer) Write

func (t *Printer) Write(b []byte) (int, error)

Write writes the bytes using the underlying writer. Does nothing if Printer has failed.

type Stepper

type Stepper struct {
	// contains filtered or unexported fields
}
Example
var (
	src  = "input.txt"
	dst  = "output.txt"
	in   *os.File
	out  *os.File
	err  error
	next = NewStepper(&err)
)

next.Step(func() {
	in, err = os.Open(src)
})

next.Stepf("create", func() {
	out, err = os.Create(dst)
})

next.Stepf("copy", func() {
	_, err = io.Copy(out, in)
})

fmt.Println(err)
Output:

open input.txt: no such file or directory

func NewStepper

func NewStepper(err *error) *Stepper

func (*Stepper) Step

func (me *Stepper) Step(step func())

Step checks internal error before calling the next step.

func (*Stepper) Stepf

func (me *Stepper) Stepf(format string, step func())

Stepf checks internal error before calling the next step. If error is set after step it's wrapped using the given format string, which must contain one optional %w. If format does not contain %w the format will be extended with ': %w' at the end.

type Writer added in v0.6.0

type Writer struct {
	Err error
	// Total number of bytes written
	Written int64
	// contains filtered or unexported fields
}

func NewWriter added in v0.6.0

func NewWriter(w io.Writer) *Writer

NewWriter returns a writer nexus. The referenced error is set by all methods if an error occurs.

func (*Writer) Done added in v0.6.0

func (t *Writer) Done() (int64, error)

Done returns total written bytes and error if any

func (*Writer) Write added in v0.6.0

func (t *Writer) Write(b []byte) (int, error)

Write writes the bytes using the underlying writer. Does nothing if previous writes have failed.

func (*Writer) WriteBinary added in v0.6.0

func (t *Writer) WriteBinary(m ...interface{})

WriteBinary writes binary data to the underlying writer. If given value implements encoding.BinaryMarshaler, the bytes from marshaling are written. Types []byte and byte are also recognized, panics on other data.

Jump to

Keyboard shortcuts

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