web-dev-qa-db-ja.com

Go構造体にデフォルト値を設定する方法

以下の質問には複数の回答/テクニックがあります。

  1. Golang構造体にデフォルト値を設定するにはどうすればいいですか?
  2. Golangで構造体を初期化する方法

いくつか答えがありますが、さらに議論が必要です。

92
Prateek
  1. メソッドに構造体を取得させる(コンストラクタの方法)。

    良い設計はあなたの型を未エクスポートにすることですが、あなたが正しくあなたの構造体/型を初期化することができるNewMyType()のようなエクスポートされたコンストラクタ関数を提供することです。具象型ではなくインタフェース型も返します。インタフェースには、他の人があなたの値でやりたいことがすべて含まれているはずです。そしてあなたの具象型はもちろんそのインターフェースを実装しなければなりません。

    これは単に型自体をエクスポートされていないものにすることで実現できます。あなたは関数NewSomethingそしてフィールドTextやDefaultTextさえもエクスポートすることができますが、struct type somethingをエクスポートしないでください

  2. 自分のモジュール用にカスタマイズするもう一つの方法は、 Config structを使ってデフォルト値を設定することです (リンク内のオプション5)。

41
Prateek

考えられるアイデアの1つは、別のコンストラクタ関数を書くことです。

//Something is the structure we work with
type Something struct {
     Text string 
     DefaultText string 
} 
// NewSomething create new instance of Something
func NewSomething(text string) Something {
   something := Something{}
   something.Text = text
   something.DefaultText = "default text"
   return something
}
67
vodolaz095

Victor Zamanianが回答したオプション1の問題の1つは、型がエクスポートされない場合、パッケージのユーザがそれを関数パラメータなどの型として宣言できないことです。これを回避する1つの方法はインタフェースの代わりにインタフェースをエクスポートすることです。 struct eg.

package candidate
// Exporting interface instead of struct
type Candidate interface {}
// Struct is not exported
type candidate struct {
    Name string
    Votes unit32 // Defaults to 0
}
// We are forced to call the constructor to get an instance of candidate
func New(name string) Candidate {
    return candidate{name, 0}  // enforce the default value here
}

これにより、エクスポートされたCandidateインタフェースを使用して関数パラメータ型を宣言できます。この解決策から私が見ることができる唯一の不利な点は、私たちのすべてのメソッドがインターフェース定義の中で宣言される必要があるということです、しかしあなたはそれがとにかく良い習慣であると主張できます。

16
wolfson109

タグを使用してこれを行う方法があり、複数のデフォルトを使用できます。

2つのデフォルトタグdefault0およびdefault1を持つ次の構造体があるとします。

type A struct {
   I int    `default0:"3" default1:"42"`
   S string `default0:"Some String..." default1:"Some Other String..."`
}

これで、デフォルトを設定できるようになりました。

func main() {

ptr := &A{}

Set(ptr, "default0")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=3 ptr.S=Some String...

Set(ptr, "default1")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=42 ptr.S=Some Other String...
}

遊び場での完全なプログラム です。

より複雑な例に興味がある場合、たとえばスライスやマップを使用する場合は、 creasty/defaultse をご覧ください

3
Mike Chirico

から https://golang.org/doc/effective_go.html#composite_literals

この例のようにパッケージosから派生したように、ゼロ値が十分ではなく、初期化コンストラクタが必要な場合があります。

    func NewFile(fd int, name string) *File {
      if fd < 0 {
        return nil
      }
      f := new(File)
      f.fd = fd
      f.name = name
      f.dirinfo = nil
      f.nepipe = 0
      return f
}
2
RdB
type Config struct {
    AWSRegion                               string `default:"us-west-2"`
}
1
user10209901