[Golang] Golang アドバンスト シリーズ チュートリアル -- Go 言語の new キーワードと make キーワードの違い

序文

この記事では、面接でよくある質問を紹介します。どのくらい一般的ですか? おそらく多くのインタビューの冒頭の言葉はここから始まるのでしょう。これが、new と make の 2 つの組み込み関数の違いです。

Go 言語には、比較的よく似た 2 つの組み込み関数、つまり new メソッドと make メソッドがあり、それらの主な目的は、対応するタイプのメモリ空間を割り当てることです。
new と make は両方ともメモリを割り当てるようですが、両者の違いは何ですか? この詳細な点は、多くの Go 言語エンジニアの面接質問の 1 つにもなっているため、一見の価値があります。

実は問題自体は複雑ではなく、簡単に言うとnewはメモリを割り当てるだけ、makeはslice、map、chanの初期化にしか使えないので、以下で詳しく紹介していきます。

新しい

new は、メモリの一部を割り当て、そのメモリへのポインタを返す組み込み関数です。
その関数シグネチャは次のとおりです。

ソースコード

// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
func new(Type) *Type

上記のコードからわかるように、新しい関数は型である 1 つのパラメーターのみを受け取り、その型のメモリ アドレスへのポインターを返します。
同時に、新しい関数は割り当てられたメモリをゼロ、つまり型のゼロ値に設定します。

使用

新しい関数を使用して、変数にメモリ領域を割り当てます。

p1 := new(int)
fmt.Printf("p1 --> %#v \n ", p1) //(*int)(0xc42000e250) 
fmt.Printf("p1 point to --> %#v \n ", *p1) //0

var p2 *int
i := 0
p2 = &i
fmt.Printf("p2 --> %#v \n ", p2) //(*int)(0xc42000e278) 
fmt.Printf("p2 point to --> %#v \n ", *p2) //0

上記のコードは同等で、 new(int) は割り当てられた領域を int のゼロ値、つまり 0 に初期化し、int のポインタを返します。これは、ポインタを直接宣言して初期化するのと同じです。

もちろん、新しい関数はシステムのデフォルトのデータ型にスペースを割り当てるだけでなく、以下に示すように、ユーザー定義型も新しい関数を使用してスペースを割り当てることができます。

type Student struct {
    
    
   name string
   age int
}
var s *Student
s = new(Student) //分配空间
s.name = "zhangsan"
fmt.Println(s)

これは新しい関数で、常に型ポインターを返し、ポインターは割り当てられた型のメモリ アドレスを指します。新しい関数はメモリ空間を割り当てるだけであり、メモリ空間を初期化しないことに注意してください。

作る

make はメモリ割り当てにも使用されますが、new とは異なり、スライス、マップ、チャンのメモリ作成にのみ使用され、返される型はポインタ型ではなく、これら 3 つの型そのものです。これら 3 つの型自体は参照型であるため、それらへのポインタを返す必要はありません。
その関数シグネチャは次のとおりです。

ソースコード

// The make built-in function allocates and initializes an object of type
// slice, map, or chan (only). Like new, the first argument is a type, not a
// value. Unlike new, make's return type is the same as the type of its
// argument, not a pointer to it. The specification of the result depends on
// the type:
// Slice: The size specifies the length. The capacity of the slice is
// equal to its length. A second integer argument may be provided to
// specify a different capacity; it must be no smaller than the
// length, so make([]int, 0, 10) allocates a slice of length 0 and
// capacity 10.
// Map: An empty map is allocated with enough space to hold the
// specified number of elements. The size may be omitted, in which case
// a small starting size is allocated.
// Channel: The channel's buffer is initialized with the specified
// buffer capacity. If zero, or the size is omitted, the channel is
// unbuffered.
func make(t Type, size ...IntegerType) Type

上記のコードから、make 関数の t パラメータは、slice、map、chan のいずれかでなければならず、戻り値も型そのものであることがわかります。

使用

例としてスライスを使用してみましょう。

var s1 []int
if s1 == nil {
    
    
    fmt.Printf("s1 is nil --> %#v \n ", s1) // []int(nil)
}

s2 := make([]int, 3)
if s2 == nil {
    
    
    fmt.Printf("s2 is nil --> %#v \n ", s2)
} else {
    
    
    fmt.Printf("s2 is not nill --> %#v \n ", s2)// []int{0, 0, 0}
}

スライスのゼロ値は nil ですが、make を使用して初期化した後、スライスの内容は []int{0, 0, 0} などの int 型のゼロ値で埋められます。
マップとチャンも似ているので、これ以上は言いません。

要約する

上記の分析を通じて、new と make の主な違いは次のように要約されます。

  • make は、slice、map、chan タイプのデータの割り当てと初期化にのみ使用できます。new は任意のタイプのデータを割り当てることができます。
  • 新しい割り当ては、*Type 型のポインターを返します。make は型自体、Type を返します。
  • new によって割り当てられたスペースはゼロに設定されます。make がスペースを割り当てた後、初期化されます。

おすすめ

転載: blog.csdn.net/u011397981/article/details/131999964