首页 > 编程笔记 > Go语言笔记 阅读:7

Go语言new()和make()函数的区别(附带实例)

在 Go 语言中,内置函数 new() 和 make() 都用于内存分配。

new() 只分配内存,而 make() 为切片、集合以及通道的数据类型分配内存和初始化。

Go new()函数

首先分析内置函数 new(),在 GoLand 中查看 new() 源码信息,源码说明如下:
func new(Type) *Type
new() 语法说明如下:
根据语法定义分别创建整型、字符串、集合、切片和通道的变量,示例代码如下:
package main

import "fmt"

func main() {
    // 为变量myInt创建Int类型的内存地址
    myInt := new(int)
    fmt.Printf("myInt类型:%T,数值:%v,地址:%v\n", *myInt,*myInt,myInt)

    // 为变量myStr创建String类型的内存地址
    myStr := new(string)
    fmt.Printf("myStr类型:%T,数值:%v,地址:%v\n", *myStr,*myStr,myStr)

    // 为变量myMap创建Map类型的内存地址
    myMap := new(map[string]string)
    fmt.Printf("myMap类型:%T,数值:%v,地址:%v\n", *myMap,*myMap,myMap)

    // 为变量mySli创建Slice类型的内存地址
    mySli := new([]int)
    fmt.Printf("mySli类型:%T,数值:%v,地址:%v\n", *mySli,*mySli,mySli)

    // 为变量myChan创建Channel类型的内存地址
    myChan := new(chan string)
    fmt.Printf("myChan类型:%T,数值:%v,地址:%v\n", *myChan,*myChan,myChan)
}
运行上述代码,运行结果为:

myInt类型:int,数值:0,地址:0xc0000ac058
myStr类型:string,数值:,地址:0xc000088230
myMap类型:map[string]string,数值:map[],地址:&map[]
mySli类型:[]int,数值:[],地址:&[]
myChan类型:chan string,数值:<nil>,地址:0xc0000d8028


结合运行结果与内置函数 new() 的特性,我们能得出以下结论:
1) 内置函数 new() 适用于所有数据类型。

2)使用 new() 创建变量,其变量值以指针方式表示,并且指针存储的数据为零,如整型为 0,字符串为空字符串,布尔为 false,切片为空切片,集合为空集合等。

new() 创建的变量以指针表示,那么它与指针之间又存在怎样的关系呢?我们通过下面的例子加以说明:
package main

import "fmt"

func main() {
    // 为变量myInt创建Int类型的内存地址
    myInt := new(int)
    // 给变量myInt赋值
    *myInt = 666
    fmt.Printf("myInt类型:%T,数值:%v,地址:%v\n", *myInt,*myInt,myInt)

    // 定义指针变量myPro
    var myPro *int
    // 输出指针变量的信息
    fmt.Printf("myPro类型:%T,数值:%v,地址:%v\n", myPro,myPro,myPro)
    // 定义变量num并赋值
    num := 777
    // 将变量num的内存地址赋予指针myPro
    myPro = &num
    // 输出指针变量的信息
    fmt.Printf("myPro类型:%T,数值:%v,地址:%v\n", *myPro,*myPro,myPro)
}
运行上述代码,运行结果为:

myInt类型:int,数值:666,地址:0xc0000180a8
myPro类型:*int,数值:<nil>,地址:<nil>
myPro类型:int,数值:777,地址:0xc0000180f0


从运行结果看到,内置函数 new() 与指针的差异说明如下:
1) 内置函数 new() 创建的变量是指针变量,并且已分配了对应的内存地址,可以直接对变量执行赋值操作。以直接对变量执行赋值操作。

2) 使用 var 定义指针变量,它的数据和内存地址皆为空值(nil),操作指针变量必须设置具体的内存地址,因此还需要绑定某个变量的内存地址。

3) 内置函数 new() 等于实现了指针的定义与赋值过程,指针赋值是指针变量设置具体的内存地址,并不是在内存地址中存放数值。

Go make()函数

内置函数 make() 仅用于分配和初始化切片、集合以及通道的数据类型。

在 GoLand 中查看 make() 源码信息,源码及注释说明如下:
func make(t Type, size ...IntegerType) Type
make() 语法说明如下:
根据 make() 语法定义分别创建切片、集合以及通道的变量,示例代码如下:
package main

import "fmt"

func main() {
    // 创建切片类型的变量mySli,切片长度和容量为10
    mySli := make([]int, 10)
    // 对切片第一个元素赋值
    mySli[0] = 666
    // 输出切片信息
    fmt.Printf("mySli数值:%v,长度:%v,容量:%v\n",mySli,len(mySli),cap(mySli))

    // 创建集合类型的变量myMap
    myMap := make(map[string]string)
    // 设置集合的成员值
    myMap["name"] = "Tom"
    // 输出集合信息
    fmt.Printf("myMap数值:%v,成员数量:%v\n", myMap, len(myMap))

    // 创建通道类型的变量myChan,容量为10
    myCh := make(chan string, 10)
    // 往通道写入数据
    myCh <- "hello"
    // 输出通道信息
    fmt.Printf("myCh数值:%v,已用缓存:%v,容量:%v\n",myCh,len(myCh),cap(myCh))
}
运行上述代码,运行结果为:

mySli数值:[666 0 0 0 0 0 0 0 0 0],长度:10,容量:10
myMap数值:map[name:Tom],成员数量:1
myCh数值:0xc0000e4060,已用缓存:1,容量:10

从上述示例得知:
1) 内置函数 make() 能直接创建切片、集合以及通道的变量。

2) 变量的值为零,如切片为空切片,每个切片元素为0或空字符串;集合为空集合,没有任何成员;通道为空通道,不寄存任何数据。

综上所述,内置函数 new() 和 make() 的区别如下:
1) new() 适用于所有数据类型,make() 仅适用于切片、集合以及通道的数据类型。

2) new() 创建的变量以指针形式表示,make() 创建的变量是某个数据类型的变量。

3) new() 仅有参数 Type,代表变量的数据类型;make() 的参数 Type 代表变量的数据类型,参数 size...IntegerType 是可选参数,用于设置切片、集合、通道的长度或容量。

相关文章