Options mode

This paper describes the application of functional languages ​​Go mode options and the design patterns in the actual programming.

Why do we need functional option mode?

I recently go-micro / options.go source code, I found a piece of code about the service registration are as follows:

type Options struct {
    Broker    broker.Broker
    Cmd       cmd.Cmd
    Client    client.Client
    Server    server.Server
    Registry  registry.Registry
    Transport transport.Transport

    // Before and After funcs
    BeforeStart []func() error
    BeforeStop  []func() error
    AfterStart  []func() error
    AfterStop   []func() error

    // Other options for implementations of the interface
    // can be stored in a context
    Context context.Context
}

func newOptions(opts ...Option) Options {
    opt := Options{
        Broker:    broker.DefaultBroker,
        Cmd:       cmd.DefaultCmd,
        Client:    client.DefaultClient,
        Server:    server.DefaultServer,
        Registry:  registry.DefaultRegistry,
        Transport: transport.DefaultTransport,
        Context:   context.Background(),
    }

    for _, o := range opts {
        o(&opt)
    }

    return opt
}

At that time it is not very clear newOptionsthis constructor why you wrote, but also to see people behind the recurrence of similar code to ask why you wrote in the micro-channel group, and later, when discussed in the group know that it is a design patterns - functional mode option .

May we see now is not quite understand what I'm talking about the problem in the end is that I keep it simple and refined look.

We now have a structure defined as follows:

type Option struct {
    A string
    B string
    C int
}

Now we need to prepare for a constructor, we could write the following in this way:

func newOption(a, b string, c int) *Option {
    return &Option{
        A: a,
        B: b,
        C: c,
    }
}

The above code is well understood, but also we have been written. Any questions?

We now consider the following two questions:

  1. We may need to specify default values ​​for Option Fields
  2. Option field member may change happen

Options mode

We first define a OptionFuncfunction type

type OptionFunc func(*Option)

It is then prepared using a closure set value for each field With function:

func WithA(a string) OptionFunc {
    return func(o *Option) {
        o.A = a
    }
}

func WithB(b string) OptionFunc {
    return func(o *Option) {
        o.B = b
    }
}

func WithC(c int) OptionFunc {
    return func(o *Option) {
        o.C = c
    }
}

Then, we define a default Optionas follows:

var (
    defaultOption = &Option{
        A: "A",
        B: "B",
        C: 100,
    }
)

Finally, we write the new constructor as follows:

func newOption2(opts ...OptionFunc) (opt *Option) {
    opt = defaultOption
    for _, o := range opts {
        o(opt)
    }
    return
}

have a test:

func main() {
    x := newOption("nazha", "小王子", 10)
    fmt.Println(x)
    x = newOption2()
    fmt.Println(x)
    x = newOption2(
        WithA("沙河娜扎"),
        WithC(250),
    )
    fmt.Println(x)
}

Output:

&{nazha 小王子 10}
&{A B 100}
&{沙河娜扎 B 250}

Such a style option using the constructor function design pattern is realized. Such defaults have been, and then later want to add a new field to the Option will not affect the previous code.

Recommended reading:

Go functional mode option

Guess you like

Origin www.cnblogs.com/nickchen121/p/11517449.html