1. ホーム
  2. スクリプト・コラム
  3. ゴラン

GO機能オプションパターン

2022-02-14 15:36:30

Golangの開発者が遭遇する多くの問題の1つは、関数の引数をオプショナルにしようとすることです。これは非常に一般的なユースケースで、いくつかのオブジェクトは基本的なデフォルトをそのまま使うべきで、時にはもっと詳細な設定をする必要があるかもしれません。

多くの言語では、これは簡単です。C言語では、引数の数が異なる複数のバージョンの同じ関数を提供できます。PHPのような言語では、引数にデフォルト値を与えて、メソッドを呼び出すときにそれを無視することが可能です。しかしGolangでは、この2つのアプローチのどちらも使うことができません。では、ユーザが追加設定を指定できるような関数を作るにはどうしたらいいでしょうか?

これを行うには多くの方法が考えられますが、そのほとんどは要件を満たしていなかったり、サーバー側のコードで余分なチェックや検証が必要だったり、クライアントが気にしないような余分なパラメータを渡してクライアントに余計な仕事をさせたりするものです。

以下は、GOのFunctional Options Pattern (FOP)を説明したもので、読み方は次のとおりです。

Optionパターンの長所と短所
長所
    1. 複数のパラメータを渡すことができ、パラメータの数や種類が変わっても互換性を保つことができます。
    2. 任意の順序でパラメータを渡す
    3. デフォルト値対応
    4. 拡張が容易
デメリット
    1.多くの機能を追加し、コストアップにつながる
    2. パラメータがあまり複雑でない場合は、できるだけ少ない数で使用する

DEMO

package main

import "fmt"

type Client struct {
	Id int64
	AppKey string
	AppSecret string
AppSecret string }

type Option func(*Client) // The arguments to the go function are passed as values, so if you want to modify the Client (the default value) you must pass the pointer

func WithAppKey(appKey string) Option {
	return func(client *Client) {
		client.AppKey = appKey
	AppKey = appKey }
}

func WithAppSecret(appSecret string) Option {
	return func(client *Client) {
		client.AppSecret = appSecret
	}
}

//
// NewClient
// @Description sets the parameters of a function to optional functions
// @param id Fixed parameters, or you can put all in optional opts
// @param opts
// @return Client returns *Client and Client can both be
//
func NewClient(id int64, opts . .Option) Client {
	o := Client{
		Id: id,
		AppKey: "key_123456",
		AppSecret: "secret_123456",
	}

	for _, opt := range opts {
		opt(&o) // go function arguments are value passed so to modify Client (default) you must pass the pointer
	}

	return o
}

func main() {
	// Use the default value
	fmt.Println(NewClient(1)) // {1 key_123456 secret_123456}
	// use the passed in values
	fmt.Println(NewClient(2, WithAppKey("change_key_222"))) // {2 change_key_222 secret_123456}
	// Pass in out of order
	fmt.Println(NewClient(3, WithAppSecret("change_secret_333"))) // {3 key_123456 change_secret_333}
	fmt.Println(NewClient(4, WithAppSecret("change_secret_444"), WithAppKey("change_key_444"))) // {4 change_key_444 change_secret_444}
}

ここまでがGO Functional Options Patternに関する記事です。GO Functional Options Patternの詳細については、過去の記事を検索していただくか、引き続き以下の記事をご覧ください。