Explication détaillée de la différence entre golang make et new

  table des matières

Un, nouveau

Deux, fais

Troisièmement, la différence entre nouveau et faire


Beaucoup d'amis n'ont pas compris pourquoi il y avait deux fonctions pour allouer de la mémoire lorsqu'ils sont entrés en contact avec Golang pour la première fois: nouveau et faire. Comme le dit le dicton: l'existence est raisonnable. Expliquons en détail la différence entre les deux. 

Un, nouveau

Regardez d'abord la déclaration de fonction:

func new(Type) *Type

new est une fonction intégrée de Golang, utilisée pour allouer de la mémoire. Le premier paramètre est le type et la valeur renvoyée est le pointeur du type. Sa valeur est initialisée à "zéro" (valeur zéro correspondant au type, int est initialisé à 0, bool initialisé à false, etc.).

Par exemple:

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

Production:

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

Comme on peut le voir dans l'exemple ci-dessus, la valeur «zéro» initialisée diffère selon le type. L'entier est initialisé à 0, la chaîne est initialisée à vide et le type booléen est initialisé à faux. 

Deux, fais

Regardez d'abord la déclaration de fonction: 

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

make est une fonction intégrée de Golang. Elle n'est utilisée que pour allouer et initialiser les types d'objets slice, map et channel. Les trois types sont des structures. La valeur de retour est un type, pas un pointeur.

Structure du code source de tranche:

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

Mapper la structure du code source:

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

Structure de la source du canal:

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
}

 Par exemple:

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

Production:

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

Troisièmement, la différence entre nouveau et faire

1. new et make sont utilisés pour allouer de la mémoire;

2. Les deux nouveaux et make allouent de la mémoire sur le tas;

3. New alloue de la mémoire pour les types de pointeur et la valeur de retour est un pointeur de type d'allocation. New ne peut pas allouer directement de la mémoire pour la tranche, la carte et le canal;

4. Make n'est utilisé que pour l'initialisation de slice, map et channel, et la valeur de retour est le type lui-même, pas un pointeur;

 

Je suppose que tu aimes

Origine blog.csdn.net/u011074149/article/details/111567784
conseillé
Classement