Crystal
Crystal

Reputation: 29458

Go constructor type

I was wondering if someone could explain this syntax to me:

// Client may be used to make requests to the Google Maps WebService APIs
type Client struct {
    httpClient        *http.Client
    apiKey            string
    baseURL           string
    clientID          string
    signature         []byte
    requestsPerSecond int
    rateLimiter       chan int
}

// ClientOption is the type of constructor options for NewClient(...).
type ClientOption func(*Client) error

var defaultRequestsPerSecond = 10

// NewClient constructs a new Client which can make requests to the Google Maps WebService APIs.
func NewClient(options ...ClientOption) (*Client, error) {
    c := &Client{requestsPerSecond: defaultRequestsPerSecond}
    WithHTTPClient(&http.Client{})(c)
    for _, option := range options {
        err := option(c)
        if err != nil {
            return nil, err
        }
    }
    .....

I don't understand what's going on with ClientOption. Is it a function type on pointer to client that returns an error? And then in NewClient, it looks like it takes in an array of ClientOption types and returns a new pointer to a Client. I'm not sure if that's right and if anyone can explain that more or give me an analogy similar to what a lot of Javascript libraries do with

options: {
    property1: "someproperty",
    property2: "anotherproperty"
}

in a constructor.

Upvotes: 0

Views: 407

Answers (1)

Mark
Mark

Reputation: 7071

A ClientOption is a function accepting a client pointer and returning an error (probably nil).

For example, here's a timeout function creating a ClientOption function:

func WithTimeout(duration time.Duration) ClientOption {
    return func(c *Client) error {
        c.timeout = duration
        return nil
    }
}

The NewClient function accepts a variable number of ClientOption parameters, available in the 'options' slice. It creates a new Client, configures it by passing client pointer to each ClientOption, and returns the pointer.

It could be used as follows:

client := NewClient(WithTimeout(3 * time.Second))

See self referential functions by Rob Pike, and Dave Cheney's options article.

Upvotes: 3

Related Questions