質問
Go にはオプションのパラメータを指定できますか?それとも、同じ名前で引数の数が異なる 2 つの関数を定義することはできますか?
解決
Goは、オプションのパラメータを持っていません。またをオーバーロードする方法をサポートしています:
その場合は、メソッドのディスパッチが簡略化されています ようなタイプのマッチングを行う必要はありません。 うまく。他の言語の使用経験 の様々なを持っていることを語ってくれました 同じ名前のメソッドが、 異なる署名は時折でした 便利それはまた、可能性があること 実際には混乱と壊れやすいです。 名前だけでマッチングし、必要 タイプの一貫性が大きなました ゴーのタイプで決定を簡素化 システムます。
他のヒント
オプションのパラメータのような何かを達成するための良い方法は、可変長引数を使用することです。この関数は、実際にあなたが指定したどんなタイプのスライスを受けています。
func foo(params ...int) {
fmt.Println(len(params))
}
func main() {
foo()
foo(1)
foo(1,2,3)
}
あなたはパラメータを含んでいる構造体を使用することができます:
type Params struct {
a, b, c int
}
func doIt(p Params) int {
return p.a + p.b + p.c
}
// you can call it without specifying all parameters
doIt(Params{a: 1, c: 9})
任意の、潜在的に多数のオプションのパラメータについては、次のような良いイディオムを使用します。 機能オプション.
あなたのタイプに合わせて Foobar
, 、まずコンストラクターを 1 つだけ書きます。
func NewFoobar(options ...func(*Foobar) error) (*Foobar, error){
fb := &Foobar{}
// ... (write initializations with default values)...
for _, op := range options{
err := op(fb)
if err != nil {
return nil, err
}
}
return fb, nil
}
ここで、各オプションは Foobar を変更する関数です。次に、ユーザーが標準オプションを使用または作成するための便利な方法を提供します。例:
func OptionReadonlyFlag(fb *Foobar) error {
fb.mutable = false
return nil
}
func OptionTemperature(t Celsius) func(*Foobar) error {
return func(fb *Foobar) error {
fb.temperature = t
return nil
}
}
簡潔にするために、オプションのタイプに名前を付けることができます (遊び場) :
type OptionFoobar func(*Foobar) error
必須パラメータが必要な場合は、可変引数の前にコンストラクターの最初の引数として追加します。 options
.
主な利点は、 機能オプション イディオムは次のとおりです。
- 新しいオプションが必要になった場合でもコンストラクターの署名は同じままであるため、既存のコードを壊すことなく API を時間の経過とともに拡張できます。
- これにより、デフォルトのユースケースが最も単純になります。議論はまったくありません!
- 複素数値の初期化を細かく制御できます。
オプションのパラメータや関数のオーバーロードのいずれもが移動でサポートされています。 に...パラメータ
はありません - もありません。 C ++プログラマのドキュメントのために行くnoreferrer"> rel="nofollow href="http://golang.org/doc/go_for_cpp_programmers.html#top"
ゴー機能をサポートしていません。
オーバーロードし、ユーザーをサポートしていません。
定義演算子ます。 私は、オプションのパラメータがサポートされていません均等に明確な声明を見つけることができませんが、彼らはどちらか、サポートされていません。
あなたは以下であるものに似FUNCで非常にうまく、これをカプセル化することができます。
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
fmt.Println(prompt())
}
func prompt(params ...string) string {
prompt := ": "
if len(params) > 0 {
prompt = params[0]
}
reader := bufio.NewReader(os.Stdin)
fmt.Print(prompt)
text, _ := reader.ReadString('\n')
return text
}
この例では、デフォルトでプロンプトがコロンとそれの前にスペースがあります。 。ます。
:
。 。 。しかし、あなたは、プロンプト機能にパラメータを供給することによって、これをオーバーライドすることができます。
prompt("Input here -> ")
これは、以下のようなプロンプトになります。
Input here ->
私はparamsパラメータと可変長引数の構造の組み合わせを使用して終了しました。このように、私はいくつかのサービスによって消費された既存のインターフェイスを変更する必要はありませんでしたし、私のサービスは、必要に応じて追加のparamsを渡すことができました。 golang遊び場でのサンプルコード: https://play.golang.org/p/G668FA97Nuする
少し遅れましたが、流暢なインターフェイスが好きなら、次のように連鎖呼び出し用のセッターを設計するとよいでしょう。
type myType struct {
s string
a, b int
}
func New(s string, err *error) *myType {
if s == "" {
*err = errors.New(
"Mandatory argument `s` must not be empty!")
}
return &myType{s: s}
}
func (this *myType) setA (a int, err *error) *myType {
if *err == nil {
if a == 42 {
*err = errors.New("42 is not the answer!")
} else {
this.a = a
}
}
return this
}
func (this *myType) setB (b int, _ *error) *myType {
this.b = b
return this
}
そして、次のように呼び出します。
func main() {
var err error = nil
instance :=
New("hello", &err).
setA(1, &err).
setB(2, &err)
if err != nil {
fmt.Println("Failed: ", err)
} else {
fmt.Println(instance)
}
}
これは次のようなものです 機能オプション @Ripounetの回答で提示されたイディオムは同じ利点がありますが、いくつかの欠点があります。
- エラーが発生してもすぐには中止されないため、コンストラクターが頻繁にエラーを報告すると予想される場合は、効率が若干低下します。
- を宣言するには 1 行を費やす必要があります。
err
変数を変更してゼロにします。
ただし、小さな利点がある可能性があります。このタイプの関数呼び出しはコンパイラのインライン化が容易になるはずですが、私は実際には専門家ではありません。
言語は、メソッドのオーバーロードをサポートしていませんが、あなただけのオプション・パラメータのような可変長引数を使用することができ、また、パラメータとしてインターフェイス{}を使用することができますが、それは良い選択ではありません。
行きますあなたはマップで任意の名前付きパラメータを渡すことができます。
type varArgs map[string]interface{}
func myFunc(args varArgs) {
arg1 := "default" // optional default value
if val, ok := args["arg1"]; ok {
// value override or other action
arg1 = val.(string) // runtime panic if wrong type
}
arg2 := 123 // optional default value
if val, ok := args["arg2"]; ok {
// value override or other action
arg2 = val.(int) // runtime panic if wrong type
}
fmt.Println(arg1, arg2)
}
func Test_test() {
myFunc(varArgs{"arg1": "value", "arg2": 1234})
}