Nexus pattern
The word nexus is defined as "The means of connection between things linked in series"
. The pattern is useful in error handling sequential function calls.
Example CopyFile(from, to string)
Copying a file, if done all in one function, is unreadable due
to multiple error checking and handling. With the nexus
pattern you define a type fileIO struct
with the
error field. Each method must check the previous error and
return if it is set without doing anything. This way all
subsequent calls are no-operations.
The err field links operations.
Each method sets x.err before returning.
type fileIO struct {
err error
}
func (x *fileIO) Open(filename string) (fh *os.File) {
if x.err != nil {
return
}
fh, x.err = os.Open(filename)
return
}
func (x *fileIO) Create(filename string) (fh *os.File) {
if x.err != nil {
return
}
fh, x.err = os.Create(filename)
return
}
func (x *fileIO) Close(w io.Closer) {
if x.err != nil {
return
}
x.err = w.Close()
}
func (x *fileIO) Copy(w io.WriteCloser, r io.Reader) (n int64) {
if x.err != nil {
return
}
n, x.err = io.Copy(w, r)
if x.err != nil {
w.Close()
}
return
}
With the fileIO nexus inplace the CopyFile function is
readable and with only one error checking and handling needed.func CopyFile(src, dst string) error {
x := &fileIO{}
r := x.Open(src)
w := x.Create(dst)
x.Copy(w, r)
x.Close(w)
if x.err != nil {
os.Remove(dst)
}
r.Close()
return x.err
}