Maison > Article > développement back-end > Quelle est la différence entre make et new dans le langage go
Différences : 1. Make ne peut être utilisé que pour allouer et initialiser des données de types slice, map et chan tandis que new peut allouer n'importe quel type de données. 2. La nouvelle allocation renvoie un pointeur, qui est le type "*Type" tandis que make renvoie une référence, qui est le Type. 3. L'espace alloué par new sera effacé ; une fois que make aura alloué l'espace, il sera initialisé.
L'environnement d'exploitation de ce tutoriel : système Windows 7, GO version 1.18, ordinateur Dell G3.
new et make sont des primitives d'allocation de mémoire en langage Go. En termes simples, new alloue uniquement de la mémoire et make est utilisé pour initialiser les tranches, les cartes et les canaux. La fonction
new(T) est une fonction intégrée qui alloue de la mémoire. Elle alloue un morceau de mémoire pour chaque type, l'initialise à la valeur zéro et renvoie son adresse mémoire.
La syntaxe est 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 } }Et si ce n'est pas encore une variable ? Pouvez-vous l'attribuer directement ?
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)) }Le résultat de l'erreur est tel qu'indiqué dans les commentaires dans le code. Comment le résoudre ? Cela peut être résolu en fournissant à Go une nouvelle adresse d'initialisation.
func main() { // 第一个 string 是 key,第二个 string 是 value mapInstance := make(map[string]string, 5) mapInstance["第一名"] = "张三" mapInstance["第二名"] = "李四" mapInstance["第三名"] = "王五" fmt.Println(mapInstance) // map[第一名:张三 第三名:王五 第二名:李四] }Nous pouvons voir que l’initialisation d’une variable pointeur avec une valeur nulle n’est pas une affectation directe. Grâce à
new, un pointeur avec une valeur de 0xc000018030 est renvoyé
pointant vers le type int nouvellement attribué, avec une valeur nulle comme valeur. De plus, il est important de noter que la valeur zéro est différente selon les types de pointeurs. Pour plus de détails, vous pouvez vous référer à cet article. Ou vous pouvez parcourir le code ci-dessous. 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)
}
Ce qui précède décrit comment attribuer des valeurs après avoir traité des types ordinaires new(). Voici comment attribuer des valeurs après avoir traité des types composites (tableau, struct). Mais ici, je pense que l'auteur de l'article original a tort, car pour la tranche, la carte et le canal, new ne peut ouvrir que instance de tableau
instance de structure
rrreeefunc make(t Type, size ...IntegerType) Type
Vous pouvez voir que le deuxième paramètre est un paramètre de longueur variable, qui est utilisé pour spécifier la taille de l'alloué. mémoire, comme slice et En d'autres termes, le cap et la longueur doivent être spécifiés (le cap représente la capacité, la longueur représente la longueur, c'est-à-dire la taille qui peut être utilisée), et le cap doit être plus grand que la longueur. Je ne vais pas trop vous présenter ici le cap et la longueur de la tranche. Vous pouvez comprendre qu'il y a une maison maintenant. Cette maison est une maison brute. Elle comprend 3 chambres (cap), et 1 d'entre elles a été rénovée. (longueur). ). rrreee
Vous pouvez voir que la longueur est de 0 lors de l'attribution d'une valeur à la tranche. Quant à la raison spécifique, les amis qui la connaissent peuvent laisser un message dans la zone de commentaire.instance de trancherrreeeinstance de carterrreee
instance de canal🎜rrreee🎜🎜🎜Résumé : 🎜🎜🎜🎜la fonction make est utilisée uniquement pour la carte, la tranche et le canal, et ne renvoie pas de pointeurs. Si vous souhaitez obtenir un pointeur explicite, vous pouvez utiliser la nouvelle fonction pour allouer ou utiliser explicitement l'adresse d'une variable. 🎜🎜Les principales différences entre new et make dans le langage Go sont les suivantes : 🎜🎜🎜🎜make ne peut être utilisé que pour allouer et initialiser des données de types slice, map et chan ; new peut allouer n'importe quel type de données. 🎜🎜🎜🎜une nouvelle allocation renvoie un pointeur, qui est le type *Type ; make renvoie une référence, qui est le Type. 🎜🎜🎜🎜new L'espace alloué est effacé ; une fois que make a alloué l'espace, il sera initialisé. 🎜🎜🎜🎜【Recommandations associées : 🎜Tutoriel vidéo Go🎜, 🎜Enseignement de la programmation🎜】🎜Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!