Golang中的重要函数new和make

在Golang中声明变量会用到make和new两个重要函数

  • make内置函数分配并初始化类型(slice, map, 以及 chan)为的对象。与new一样,第一个参数是类型,而不是值. 和new相比不同的是,make函数返回的是与参数相同的返回值,不是指针。这三种类型就是引用类型,所以就没有必要返回他们的指针了。
func make(t Type, size ...IntegerType) Type
  • new函数用于分配内存,第一个参数为类型(不是值),返回的结果是一个指针(分配对应类型的0值)
func new(Type) *Type

总结:

1. 二者都是用来做内存分配的。
2. make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
3. 而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。

值类型与引用类型

  1. 值类型:变量直接存储值,内存通常在栈中分配
  2. 引用类型:变量存储的是一个地址,这个地址对于的空间才是真正的存储数据(值),内存通常在堆上分配,当没有任何变量引用这个地址时,改地址对应的数据空间就成为了一个垃圾,由GC来回收

代码示例

  • new函数
package main

import "fmt"

func main() {
    var a = new(int)
    fmt.Println(a)
}
// 输出地址:0xc000014088
  • make函数
package main

import "fmt"

func main() {
    var a = make(map[string]string, 1)
    a["name"] = "小a"
    fmt.Println(a)
}
// 输出:map[name:小a]
  • 不使用new与make时

    说明:Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化操作。每个变量会被初始化成其类型的默认值,例如: 整型和浮点型变量的默认值为0。 字符串变量的默认值为空字符串。 布尔型变量默认为false。 切片、函数、指针变量的默认为nil。

package main

import "fmt"

func main() {
    // a 引用类型
    var a = make(map[string]int)
    // b 引用类型
    var b map[string]int
    // 值类型
    var c [5]int
    var d *int
    // 对a赋值不报错(因为已分配地址)
    a["name"] = 1
    // 对b赋值报错
    // b["name"] = 1
    // 对c赋值
    c[0] = 1
    // 引用类型
    // 不初始化报错
    d = new(int)
    *d = 1
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
    fmt.Println(*d)
}

结论:虽然声明变量的时候,会自动对变量对应的内存区域进行初始化成其类型的默认值,但是引用类型的变量必须使用new或者make函数分配内存才可以进行变量的赋值操作。而值类型不需改改操作。
就是说,变量声明虽然会初始化,但是引用类型必须要使用new或者make对值进行初始化,如果引用类型的值没有初始化那么是无法直接使用的