golangmakeとnewの違いの詳細な説明

  目次

1つ、新しい

二、make

3つ目は、newとmakeの違いです


多くの友人は、Golangと最初に接触したときに、メモリを割り当てるための2つの機能がある理由を理解していませんでした:newとmake。ことわざにあるように:存在は合理的です。2つの違いを詳しく説明しましょう。 

1つ、新しい

最初に関数宣言を見てください。

func new(Type) *Type

newは、メモリの割り当てに使用されるGolangの組み込み関数です。最初のパラメータは型であり、戻り値は型のポインタです。その値は「ゼロ」(型に対応するゼロ値、 intは0に初期化され、boolはfalseに初期化されます。

例えば:

package main
import "fmt"

func main() {
	id := new(int)
	name := new(string)
	flag := new(bool)
	fmt.Printf("id type: %T  value: %v\n", id, *id)
	fmt.Printf("name type: %T  value: %v\n", name, *name)
	fmt.Printf("flag type: %T  value: %v\n", flag, *flag)
}

出力:

id type: *int  value: 0
name type: *string  value: 
flag type: *bool  value: false

上記の例からわかるように、初期化された「ゼロ」値はタイプによって異なります。整数は0に初期化され、文字列は空に初期化され、ブール型はfalseに初期化されます。 

二、make

最初に関数宣言を見てください。 

func make(t Type, size ...IntegerType) Type

makeは、Golangの組み込み関数であり、オブジェクトのスライス、マップ、およびチャネルタイプの割り当て初期化にのみ使用されます。3つのタイプはすべて構造体です。戻り値は型であり、ポインタではありません。

スライスソースコード構造:

type slice struct {
    array unsafe.Pointer  //指针
    len   int             //长度
    cap   int             //容量
}

マップのソースコード構造:

// A header for a Go map.
type hmap struct {
	// Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.
	// Make sure this stays in sync with the compiler's definition.
	count     int // # live cells == size of map.  Must be first (used by len() builtin)
	flags     uint8
	B         uint8  // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
	noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
	hash0     uint32 // hash seed

	buckets    unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
	oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
	nevacuate  uintptr        // progress counter for evacuation (buckets less than this have been evacuated)

	extra *mapextra // optional fields
}

チャネルソース構造:

type hchan struct {
	qcount   uint           // total data in the queue
	dataqsiz uint           // size of the circular queue
	buf      unsafe.Pointer // points to an array of dataqsiz elements
	elemsize uint16
	closed   uint32
	elemtype *_type // element type
	sendx    uint   // send index
	recvx    uint   // receive index
	recvq    waitq  // list of recv waiters
	sendq    waitq  // list of send waiters

	// lock protects all fields in hchan, as well as several
	// fields in sudogs blocked on this channel.
	//
	// Do not change another G's status while holding this lock
	// (in particular, do not ready a G), as this can deadlock
	// with stack shrinking.
	lock mutex
}

 例えば:

package main

import "fmt"

func main() {
	//map
	fmt.Println("map:")
	var nameId = make(map[string]int, 0)
	fmt.Printf("nameId \ntype: %#v\n", nameId)
	nameId["Golang"] = 1
	nameId["C++"] = 2
	nameId["PHP"] = 3

	for name, id := range nameId {
		fmt.Printf("name = %v, id = %v\n", name, id)
	}
	// slice
	var hobby = make([]string, 2, 100) // 其中 2是长度,100是容量
	hobby[0] = "打篮球"
	hobby[1] = "乒乓球"
	fmt.Println("\nslice:")
	fmt.Printf("length = %v  caps = %v\n", len(hobby), cap(hobby))
	for _, name := range hobby {
		fmt.Println(name)
	}
	// channel
	ch := make(chan int, 3)
	ch <- 1
	ch <- 2
	ch <- 8
	close(ch)
	fmt.Println("\nchannel:")
	for val := range ch { // 遍历数据
		fmt.Println(val)
	}
}

出力:

[root@localhost test]# go run main.go 
map:
nameId 
type: map[string]int{}
name = Golang, id = 1
name = C++, id = 2
name = PHP, id = 3

slice:
length = 2  caps = 100
打篮球
乒乓球

channel:
1
2
8
[root@localhost test]#

3つ目は、newとmakeの違いです

1.newとmakeの両方がメモリの割り当てに使用されます。

2.newとmakeの両方がヒープにメモリを割り当てます。

3. Newは、ポインタタイプにメモリを割り当て、戻り値は割り当てタイプのポインタです。Newは、スライス、マップ、およびチャネルにメモリを直接割り当てることはできません。

4. Makeは、スライス、マップ、およびチャネルの初期化にのみ使用され、戻り値はタイプ自体であり、ポインターではありません。

 

おすすめ

転載: blog.csdn.net/u011074149/article/details/111567784