Heim > Artikel > Backend-Entwicklung > Was ist der Unterschied zwischen make und new in der Go-Sprache?
Unterschiede: 1. Make kann nur zum Zuweisen und Initialisieren von Daten der Typen Slice, Map und Chan verwendet werden, während new jede Art von Daten zuordnen kann. 2. Die neue Zuweisung gibt einen Zeiger vom Typ „*Type“ zurück, während make eine Referenz vom Typ „Type“ zurückgibt. 3. Der von new zugewiesene Speicherplatz wird gelöscht. Nachdem make den Speicherplatz zugewiesen hat, wird er initialisiert.
Die Betriebsumgebung dieses Tutorials: Windows 7-System, GO Version 1.18, Dell G3-Computer.
new und make sind Grundelemente für die Speicherzuweisung in der Go-Sprache. Einfach ausgedrückt: new weist nur Speicher zu und make wird zum Initialisieren von Slices, Maps und Kanälen verwendet. Die Funktion
new(T) ist eine integrierte Funktion, die jedem Typ einen Speicher zuweist, ihn auf den Wert Null initialisiert und seine Speicheradresse zurückgibt.
Die Syntax lautet func new(Type) *Type
func new(Type) *Type
众所周知,一个已经存在的变量可以赋值给它的指针。
var p int var v *int v = &p *v = 11 fmt.Println(*v)
那么如果它还不是一个变量呢?你可以直接赋值吗?
func main() { var v *int *v = 8 fmt.Println(*v) // panic: runtime error: invalid memory address or nil pointer dereference // [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x47df36] // goroutine 1 [running]: // main.main() // /tmp/sandbox1410772957/prog.go:9 +0x16 }
报错结果如代码中的注释。
如何解决?可以通过 Go 提供 new 初始化地址来解决。
func main() { var v *int // v 是一个 int 类型的指针,v 的地址和 v 的值 0xc0000ba018 <nil> fmt.Println("v 是一个 int 类型的指针,v 的地址和 v 的值 ", &v, v) // 分配给 v 一个指向的变量 v = new(int) // v 是一个 int 类型的指针,v 的地址和 v 的值 0xc0000ba018 0xc000018030 0,此时已经分配给了 v 指针一个指向的变量,但是变量为零值 fmt.Println("v 是一个 int 类型的指针,v 的地址, v 的值和 v 指向的变量的值 ", &v, v, *v) *v = 8 // v 是一个 int 类型的指针,v 的地址和 v 的值 0xc0000ba018 0xc000018030 8,此时又像这个变量中装填了一个值 8 fmt.Println("v 是一个 int 类型的指针,v 的地址, v 的值和 v 指向的变量的值 ", &v, v, *v) // 整个过程可以理解为给 v 指针指向了一个匿名变量 }
我们可以看到,初始化一个值为nil的指针变量并不是直接赋值。通过new返回一个值为0xc000018030 的指针指向新赋值的int类型,零值为其值。
此外,重要的是要注意,不同指针类型的零值是不同的。具体的你可以参考这篇文章。或者你可以浏览下面的代码。
type Name struct { P string } var av *[5]int var iv *int var sv *string var tv *Name av = new([5]int) fmt.Println(*av) //[0 0 0 0 0 0] iv = new(int) fmt.Println(*iv) // 0 sv = new(string) fmt.Println(*sv) // tv = new(Name) fmt.Println(*tv) //{}
上面介绍了处理普通类型new()后如何赋值,这里是处理复合类型(array、struct)后如何赋值。但是在这里,我认为原文的作者讲述有错误,因为对 slice,map 和 channel 来说,new 只能开辟
数组实例
func main() { // 声明一个数组指针 var a *[5]int fmt.Printf("a: %p %#v \n", &a, a) //a: 0xc04200a180 [5]int{0, 0, 0, 0, 0} // 分配一个内存地址给 a(数组指针)指向 a = new([5]int) fmt.Printf("a: %p %#v \n", &a, a) //av: 0xc000074018 &[5]int{0, 0, 0, 0, 0} // 修改这个数组中的值 (*a)[1] = 8 fmt.Printf("a: %p %#v \n", &a, a) //av: 0xc000006028 &[5]int{0, 8, 0, 0, 0} }
结构体实例
type mystruct struct { name string age int } func main() { var people *mystruct people = new(mystruct) people.name = "zhangsan" people.age = 11 fmt.Printf("%v, %v", people.name, people.age) // zhangsan, 11 }
make 专门用于创建 chan,map 和 slice 三种类型的内容分配,并且可以初始化它们。make 的返回类型与其参数的类型相同,而不是指向它的指针,因为这三种数据类型本身就是引用类型。
其语法为:func make(t Type, size ...IntegerType) Type
func main() { var s *[]int fmt.Printf("s 的地址是: %p, s 的值是 %p\n", &s, s) // s 的地址是: 0xc00000e028, s 的值是 0x0 s = new([]int) fmt.Printf("s 的地址是: %p, s 的值是 %p\n", &s, s) // s 的地址是: 0xc00000e028, s 的值是 0xc00011a018 (*s)[0] = 1 fmt.Println("s 的地址是: %p, s 的值是 %p\n", &s, s) // panic: runtime error: index out of range [0] with length 0 } }Und was ist, wenn es noch keine Variable ist? Kann man es direkt zuordnen?
func main() { // 第一个 size 是 length,第二个 size 是 cap a := make([]int, 5, 10) // a: 0xc00011a018 []int{0, 0, 0, 0, 0},cap: 10, length: 5 fmt.Printf("a: %p %#v,cap: %d, length: %d \n", &a, a, cap(a), len(a)) }Das Fehlerergebnis ist wie in den Kommentaren im Code gezeigt. Wie kann man es lösen? Dies kann gelöst werden, indem Go eine neue Initialisierungsadresse bereitstellt.
func main() { // 第一个 string 是 key,第二个 string 是 value mapInstance := make(map[string]string, 5) mapInstance["第一名"] = "张三" mapInstance["第二名"] = "李四" mapInstance["第三名"] = "王五" fmt.Println(mapInstance) // map[第一名:张三 第三名:王五 第二名:李四] }Wir können sehen, dass die Initialisierung einer Zeigervariablen mit dem Wert Null keine direkte Zuweisung ist. Through
new gibt einen Zeiger mit dem Wert 0xc000018030
zurück, der auf den neu zugewiesenen int-Typ zeigt, mit dem Wert Null als Wert. Außerdem ist zu beachten, dass der Nullwert für verschiedene Zeigertypen unterschiedlich ist. Einzelheiten finden Sie in diesem Artikel. Oder Sie können den Code unten durchsuchen. func countNum(temp int, ch chan int) {
i := temp + 1
ch <- i
fmt.Println("已经将 i 发往通道 c 中")
}
func main() {
ch := make(chan int)
go countNum(1, ch)
res := <-ch
fmt.Println("已经从 ch 中获取 i 并保存在 res 中")
fmt.Println("res 是", res)
}
Oben wird beschrieben, wie Werte nach der Verarbeitung gewöhnlicher Typen new() zugewiesen werden. Hier erfahren Sie, wie Sie Werte nach der Verarbeitung zusammengesetzter Typen (Array, Struktur) zuweisen. Aber hier liegt meiner Meinung nach der Autor des Originalartikels falsch, denn für Slice, Map und Channel kann new nur Array-Instanz
Strukturinstanz
rrreeefunc make(t Type, size ...IntegerType) Type
Sie können sehen, dass der zweite Parameter ein Parameter variabler Länge ist, der zur Angabe der Größe des zugewiesenen Parameters verwendet wird B. Slice und Mit anderen Worten, die Obergrenze und die Länge müssen angegeben werden (die Obergrenze stellt die Kapazität dar, die Länge stellt die Länge dar, dh die Größe, die verwendet werden kann), und die Obergrenze muss größer als die Länge sein. Ich werde hier nicht zu viel über die Obergrenze und die Länge des Abschnitts sagen. Sie können verstehen, dass es sich bei diesem Haus um ein Rohhaus handelt, von dem eines renoviert wurde (Länge). ). rrreee
Sie können sehen, dass die Länge 0 beträgt, wenn Sie Slice einen Wert zuweisen. Was den konkreten Grund betrifft, können Freunde, die es wissen, eine Nachricht im Kommentarbereich hinterlassen.Slice-InstanzrrreeeKarteninstanzrrreee
Kanalinstanz🎜rrreee🎜🎜🎜Zusammenfassung: 🎜🎜🎜🎜make-Funktion wird nur für Map, Slice und Channel verwendet und gibt keine Zeiger zurück. Wenn Sie einen expliziten Zeiger erhalten möchten, können Sie die neue Funktion zum Zuweisen verwenden oder explizit die Adresse einer Variablen verwenden. 🎜🎜Die Hauptunterschiede zwischen new und make in der Go-Sprache sind wie folgt: 🎜🎜🎜🎜make kann nur zum Zuweisen und Initialisieren von Daten der Typen Slice, Map und Chan verwendet werden; new kann jede Art von Daten zuordnen. 🎜🎜🎜🎜Neue Zuweisung gibt einen Zeiger zurück, der vom Typ *Type ist; make gibt eine Referenz zurück, der Typ ist. 🎜🎜🎜🎜new Der zugewiesene Speicherplatz wird gelöscht. Nachdem make den Speicherplatz zugewiesen hat, wird er initialisiert. 🎜🎜🎜🎜【Verwandte Empfehlungen: 🎜Go-Video-Tutorial🎜, 🎜Programmierunterricht🎜】🎜Das obige ist der detaillierte Inhalt vonWas ist der Unterschied zwischen make und new in der Go-Sprache?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!