Abner的博客

Go中make与new区别

· 119 words · 1 minutes to read
Categories: Go

Table of Contents


变量的声明 🔗

var i int
var s string

量的声明我们可以通过var关键字,然后就可以在程序中使用。当我们不指定变量的默认值时,这些变量的默认值是他们的零值,比如int类型的零值是0,string类型的零值是"",引用类型的零值是nil

对于例子中的两种类型的声明,我们可以直接使用,对其进行赋值输出。但是如果我们换成指针类型呢?

package main

import (
 "fmt"
)

func main() {
   var i *int
   *i=10
   fmt.Println(*i)
}
$ go run test1.go 
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4849df]

goroutine 1 [running]:
main.main()
	/home/itheima/go/src/golang_deeper/make_new/t

从这个提示中可以看出,对于引用类型的变量,我们不光要声明它,还要为它分配内容空间,否则我们的值放在哪里去呢?这就是上面错误提示的原因。

new 🔗

对于上面的问题我们如何解决呢?既然我们知道了没有为其分配内存,那么我们使用new分配一个吧。

func main() {
  
   var i *int
   i=new(int)
   *i=10
   fmt.Println(*i)
  
}

我们使用new关键字,为引用类型变量分配内存,然后就可以进行赋值了。现在再运行程序,PASS,打印10。

package main

import (
    "fmt"
    "sync"
)

type user struct {
    lock sync.Mutex
    name string
    age int
}

func main() {

    u := new(user) //默认给u分配到内存全部为0

    u.lock.Lock()  //可以直接使用,因为lock为0,是开锁状态
    u.name = "张三"
    u.lock.Unlock()

    fmt.Println(u)
}
$ go run test2.go 
&{{0 0} 张三 0}

这就是new,它返回的永远是类型的指针,指向分配类型的内存地址。

make 🔗

make也是用于内存分配的,但是和new不同。它只用于

  • map
  • chan
  • slice 的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。

make与new的异同 🔗

同:堆空间分配 不同:make: 只用于slice、map以及channel的初始化, 无可替代;new: 用于类型内存分配(初始化值为0), 不常用