Detailed explanation of the difference between golang make and new

  table of Contents

One, new

Two, make

Three, the difference between new and make


Many friends didn't understand why there are two functions for allocating memory when they first came into contact with Golang: new and make. As the saying goes: Existence is reasonable. Let's explain in detail the difference between the two. 

One, new

Look at the function declaration first:

func new(Type) *Type

new is a built-in function of Golang, which is used to allocate memory. The first parameter is the type and the return value is the pointer of the type. Its value is initialized to "zero" (zero value corresponding to the type, int is initialized to 0, bool Initialized to false, etc.).

E.g:

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)
}

Output:

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

As can be seen from the above example, the initialized "zero" value differs according to the type. The integer is initialized to 0, the string is initialized to empty, and the bool type is initialized to false. 

Two, make

Look at the function declaration first: 

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

make is a built-in function of Golang. It is only used to allocate and initialize slice, map, and channel types of objects. All three types are structures. The return value is a type, not a pointer.

Slice source code structure:

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

Map source code structure:

// 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
}

Channel source structure:

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
}

 E.g:

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)
	}
}

Output:

[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]#

Three, the difference between new and make

1. Both new and make are used to allocate memory;

2. Both new and make allocate memory on the heap;

3. New allocates memory for pointer types, and the return value is a pointer of allocation type. New cannot directly allocate memory for slice, map, and channel;

4. Make is only used for the initialization of slice, map and channel, and the return value is the type itself, not a pointer;

 

Guess you like

Origin blog.csdn.net/u011074149/article/details/111567784