回答:
あなたが行うことができます物事make
あなたが他の方法で行うことができません。
正当化するのは少し難しいnew
です。それが簡単にする主なことは、非複合型へのポインタを作成することです。以下の2つの関数は同等です。もう少し簡潔です。
func newInt1() *int { return new(int) }
func newInt2() *int {
var i int
return &i
}
m := map[string]int{}
の代わりにm := make(map[string]int)
?サイズを事前に割り当てる必要もありません。
Goには、メモリの割り当てと値の初期化に複数の方法があります。
&T{...}
、&someLocalVar
、new
、make
割り当ては、複合リテラルを作成するときにも発生します。
new
整数などの値を割り当てるために使用できますが、これ&int
は不正です。
new(Point)
&Point{} // OK
&Point{2, 3} // Combines allocation and initialization
new(int)
&int // Illegal
// Works, but it is less convenient to write than new(int)
var i int
&i
違いnew
とは、make
次の例を見て、見ることができます。
p := new(chan int) // p has type: *chan int
c := make(chan int) // c has type: chan int
Goにはnew
and がなくmake
、組み込み関数があるとしますNEW
。次に、コード例は次のようになります。
p := NEW(*chan int) // * is mandatory
c := NEW(chan int)
*
必須になりますので、:
new(int) --> NEW(*int)
new(Point) --> NEW(*Point)
new(chan int) --> NEW(*chan int)
make([]int, 10) --> NEW([]int, 10)
new(Point) // Illegal
new(int) // Illegal
はい、マージnew
とmake
シングルビルトイン関数にすることは可能です。ただし、1つの組み込み関数を使用すると、2つの組み込み関数を使用するよりも、新しいGoプログラマーの間で混乱が生じる可能性があります。
上記のすべての点を考慮すると、分離する方が適切であるnew
とmake
考えられます。
int
が作成されたインスタンスであることを示しています。
make(Point)
及びmake(int)
それらの最後の2行には?
make
functionは、slice、map、またはchanタイプのオブジェクトのみを割り当てて初期化します。のようnew
に、最初の引数は型です。ただし、サイズという2番目の引数を取ることもできます。newとは異なり、makeの戻り値の型は、引数へのポインタではなく、引数の型と同じです。そして、割り当てられた値は初期化されます(newのようにゼロ値に設定されません)。その理由は、slice、map、chanがデータ構造であるためです。これらは初期化する必要があります。そうしないと使用できません。これがnew()とmake()が異なる必要がある理由です。
次のEffective Goの例は、非常に明確です。
p *[]int = new([]int) // *p = nil, which makes p useless
v []int = make([]int, 100) // creates v structure that has pointer to an array, length field, and capacity field. So, v is immediately usable
new([]int)
、単に[] intにメモリを割り当てますが、初期化は行わないため、単に戻りますnil
。使用できないため、メモリへのポインタではありません。make([]int)
使用できるように割り当てて初期化し、そのアドレスを返します。
new(T)
-割り当てメモリ、およびに設定、それをゼロ値タイプのT ..
ある..that 0
ためINT、""
のための文字列とnil
参照型(のためのスライス、マップ、チャン)
参照される型は、いくつかの基になるデータ構造へのポインタにすぎないことに注意してください。これは、new(T)
例では作成されません。スライスの場合、基になる配列は作成されないためnew([]int)
、ポインタは何も返しません。
make(T)
-参照されるデータ型(slice、map、chan)にメモリを割り当て、その基礎となるデータ構造を初期化します
例:sliceの場合、基になる配列は指定された長さと容量で作成されます
。Cとは異なり、配列はGo!のプリミティブ型であることに注意してください。
言われていること:
make(T)
複合リテラル構文のように動作します
new(T)
のように動作var
します(変数が初期化されていない場合)
func main() {
fmt.Println("-- MAKE --")
a := make([]int, 0)
aPtr := &a
fmt.Println("pointer == nil :", *aPtr == nil)
fmt.Printf("pointer value: %p\n\n", *aPtr)
fmt.Println("-- COMPOSITE LITERAL --")
b := []int{}
bPtr := &b
fmt.Println("pointer == nil :", *bPtr == nil)
fmt.Printf("pointer value: %p\n\n", *bPtr)
fmt.Println("-- NEW --")
cPtr := new([]int)
fmt.Println("pointer == nil :", *cPtr == nil)
fmt.Printf("pointer value: %p\n\n", *cPtr)
fmt.Println("-- VAR (not initialized) --")
var d []int
dPtr := &d
fmt.Println("pointer == nil :", *dPtr == nil)
fmt.Printf("pointer value: %p\n", *dPtr)
}
プログラムを実行する
-- MAKE --
pointer == nil : false
pointer value: 0x118eff0 # address to underlying array
-- COMPOSITE LITERAL --
pointer == nil : false
pointer value: 0x118eff0 # address to underlying array
-- NEW --
pointer == nil : true
pointer value: 0x0
-- VAR (not initialized) --
pointer == nil : true
pointer value: 0x0
参考
資料:https : //golang.org/doc/effective_go.html#allocation_new https://golang.org/doc/effective_go.html#allocation_make
make()
チャネルとマップ(およびスライスを作成する必要がありますが、配列から作成することもできます)。これらを作成する代替方法がないためmake()
、レキシコンから削除することはできません。
についてはnew()
、構造体構文を使用できるときになぜそれが必要なのか、その理由がわかりません。ただし、「すべてのフィールドがゼロ値に初期化された構造体を作成して返す」という独特のセマンティックな意味を持つため、便利です。