Detaillierte Erklärung des Unterschieds zwischen Golang machen und neu

  Inhaltsverzeichnis

Eins, neu

Zwei, mach

Drei, der Unterschied zwischen neu und machen


Viele Freunde haben nicht verstanden, warum es zwei Funktionen zum Zuweisen von Speicher gibt, als sie zum ersten Mal mit Golang in Kontakt kamen: neu und machen. Wie das Sprichwort sagt: Existenz ist vernünftig. Lassen Sie uns den Unterschied zwischen den beiden im Detail erklären. 

Eins, neu

Schauen Sie sich zuerst die Funktionsdeklaration an:

func new(Type) *Type

new ist eine integrierte Funktion von Golang, mit der Speicher zugewiesen wird. Der erste Parameter ist der Typ und der Rückgabewert ist der Zeiger des Typs. Sein Wert wird auf "Null" initialisiert (Nullwert entsprechend dem Typ, int wird auf 0 initialisiert, bool auf false initialisiert usw.).

Z.B:

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

Ausgabe:

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

Wie aus dem obigen Beispiel ersichtlich ist, unterscheidet sich der initialisierte "Null" -Wert je nach Typ. Die Ganzzahl wird auf 0 initialisiert, die Zeichenfolge wird auf leer initialisiert und der Bool-Typ wird auf false initialisiert. 

Zwei, mach

Schauen Sie sich zuerst die Funktionsdeklaration an: 

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

Make ist eine integrierte Funktion von Golang. Es wird nur verwendet zuteilen und initialize Scheibe, Karte und Kanaltypen von Objekten. Alle drei Typen sind Strukturen. Der Rückgabewert ist ein Typ, kein Zeiger.

Slice-Quellcodestruktur:

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

Struktur des Kartenquellcodes:

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

Kanalquellenstruktur:

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
}

 Z.B:

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

Ausgabe:

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

Drei, der Unterschied zwischen neu und machen

1. Sowohl new als auch make werden zum Zuweisen von Speicher verwendet.

2. Sowohl neu als auch make Speicher auf dem Heap zuweisen;

3. Neu weist Speicher für Zeigertypen zu, und der Rückgabewert ist ein Zeiger vom Zuordnungstyp. Neu kann Speicher für Slice, Map und Kanal nicht direkt zuweisen.

4. Make wird nur für die Initialisierung von Slice, Map und Channel verwendet. Der Rückgabewert ist der Typ selbst und kein Zeiger.

 

Ich denke du magst

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