Skip to content

Parameter Objects

A parameter object is an objects with the sole purpose of carrying parameters for a specific function or method.

The object is typically defined exclusively for that function, and is not shared with other functions. That is, a parameter object is not a general purpose object like "user" but purpose-built, like "parameters for the GetUser function".

In Fx, parameter objects contain exported fields exclusively, and are always tagged with fx.In.

Related

Using parameter objects

To use parameter objects in Fx, take the following steps:

  1. Define a new struct type named after your constructor with a Params suffix. If the constructor is named NewClient, name the struct ClientParams. If the constructor is named New, name the struct Params. This naming isn't strictly necessary, but it's a good convention to follow.

    type ClientParams struct {
    }
    
  2. Embed fx.In into this struct.

    type ClientParams struct {
       fx.In
    
  3. Add this new type as a parameter to your constructor by value.

    func NewClient(p ClientParams) (*Client, error) {
    
  4. Add dependencies of your constructor as exported fields on this struct.

    type ClientParams struct {
       fx.In
    
       Config     ClientConfig
       HTTPClient *http.Client
    }
    
  5. Consume these fields in your constructor.

    func NewClient(p ClientParams) (*Client, error) {
       return &Client{
           url:  p.Config.URL,
           http: p.HTTPClient,
           // ...
       }, nil
    

Once you have a parameter object on a function, you can use it to access other advanced features of Fx:

Adding new parameters

You can add new parameters for a constructor by adding new fields to a parameter object. For this to be backwards compatible, the new fields must be optional.

  1. Take an existing parameter object.

    type Params struct {
       fx.In
    
       Config     ClientConfig
       HTTPClient *http.Client
    }
    
    func New(p Params) (*Client, error) {
    
  2. Add a new field to it for your new dependency and mark it optional to keep this change backwards compatible.

    type Params struct {
       fx.In
    
       Config     ClientConfig
       HTTPClient *http.Client
       Logger *zap.Logger `optional:"true"`
    }
    
  3. In your constructor, consume this field. Be sure to handle the case when this field is absent -- it will take the zero value of its type in that case.

    func New(p Params) (*Client, error) {
       log := p.Logger
       if log == nil {
           log = zap.NewNop()
       }
       // ...