2

私はいつも、package.New() 構文を使用するのがやや厄介であることに気づきました。

提案は、パッケージが 1 つのタイプのみを保持する場合、package.New() を使用してインスタンスを作成することです。複数のタイプが存在する場合は、package.NewBlah() を使用します。 http://golang.org/doc/effective_go.html#package-names

ただし、New() API を含む既存のパッケージがある場合、この NewFoo() の名前を変更する必要があるため、パッケージに新しい外部型を追加すると API が破損する場合、このアプローチは失敗します。ここで、New() を使用するすべてのものを変更する必要がありますが、これは非常にイライラします。

...そして、私はこれを書くことの美学に不満を持っています:

import "other"
import "bar"
import "foo"

o := other.New()  // <-- Weird, what type am I getting? No idea.
x := bar.New()  
y := foo.NewFoo() // <-- Awkward, makes constructor naming look inconsistent   
z := foo.NewBar() 

そのため、最近は代わりに次のパターンを使用しています。

x := foo.Foo{}.New()   // <-- Immediately obvious I'm getting a Foo
y := foo.Bar{}.New()   // <-- Only an additional 3 characters on NewBar{}
o := other.Foo{}.New() // <-- Consistent across all packages, no breakage on update

モジュールは次のように定義されています。

package foo

type Foo struct {
  x int
}

func (s Foo) New() *Foo {
  // Normal init stuff here
  return &s // <-- Edit: notice the single instance is returned 
}

type Bar struct {
}

func (Bar) New() *Bar {
  return &Bar{} // <-- Edit: Bad, results in double alloc. Not like this. 
}

Godoc はそれで問題なく動作するようであり、冗長性を追加することなく、より明白で一貫しているように思えます。

では、質問: これには具体的なマイナス面はありますか?

4

2 に答える 2

2

はい、欠点があります。このアプローチでは、特定のGoコンパイラ実装の最適化がどれだけ優れているかによって、不要なガベージが生成される可能性があります。

于 2013-02-22T04:25:39.010 に答える
2

あなたが指摘するように、それはひどく慣用的なものではなく、ひどく行われた場合、余分なゴミを作成する可能性があります. 基本的に、オブジェクトの Init メソッドを作成しているだけです。オブジェクトに有効なゼロ値を持ち、それが当てはまらない場合にのみコンストラクターを使用することを好む傾向があるため、私自身は多くのコンストラクターを使用しません。

あなたの場合、メソッドを new と呼ぶのをやめて、代わりに Init または Setup と呼んで、それが何をしているのかをよりよく反映すると思います。そうすれば、それが何をしているのかについて人々に間違った考えを与えることを避けることができます.

編集:

ここはもっと詳しく書くべきでした。メソッド Init または Setup を呼び出してからゼロ値で使用すると、消費者に何が起こっているかがよりよく反映されます。例えば

f := &foo{}
f.Init()

これにより、余分なゴミが回避され、説明したように初期化メソッドが提供されます。

于 2013-02-22T05:14:36.410 に答える