【Golang】设计模式 - idioms - Functional Options

Posted by 西维蜀黍 on 2021-09-18, Last Modified on 2023-08-23

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.

Demo

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)
}

Reference