1
0
mirror of https://github.com/tmrts/go-patterns.git synced 2025-02-18 05:23:14 +03:00
go-patterns/idiom/functional-options.md
Mathias Fredriksson 4cdebe4220 idiom/functional-options: Unexport options
Options is an implementation detail and adds no value by being exported.
By unexporting Options we decrease the API surface and maintain the
ability to make changes without breaking user expectations.
2018-01-06 02:36:01 +02:00

1.5 KiB

Functional Options

Functional options are a method of implementing clean/eloquent APIs in Go. Options implemented as a function set the state of that option.

Implementation

Options

package file

type options struct {
	UID         int
	GID         int
	Flags       int
	Contents    string
	Permissions os.FileMode
}

type Option func(*options)

func UID(userID int) Option {
	return func(args *options) {
		args.UID = userID
	}
}

func GID(groupID int) Option {
	return func(args *options) {
		args.GID = groupID
	}
}

func Contents(c string) Option {
	return func(args *options) {
		args.Contents = c
	}
}

func Permissions(perms os.FileMode) Option {
	return func(args *options) {
		args.Permissions = perms
	}
}

Constructor

package file

func New(filepath string, setters ...Option) error {
	// Default options
	args := &options{
		UID:         os.Getuid(),
		GID:         os.Getgid(),
		Contents:    "",
		Permissions: 0666,
		Flags:       os.O_CREATE | os.O_EXCL | os.O_WRONLY,
	}

	for _, setter := range setters {
		setter(args)
	}

	f, err := os.OpenFile(filepath, args.Flags, args.Permissions)
	if err != nil {
		return err
	} else {
		defer f.Close()
	}

	if _, err := f.WriteString(args.Contents); err != nil {
		return err
	}

	return f.Chown(args.UID, args.GID)
}

Usage

emptyFile, err := file.New("/tmp/empty.txt")
if err != nil {
    panic(err)
}

fillerFile, err := file.New("/tmp/file.txt", file.UID(1000), file.Contents("Lorem Ipsum Dolor Amet"))
if err != nil {
    panic(err)
}