11 - new() 和 make() 的恩爱情仇

在 go 语言当中有两个用于内存分配的内建函数 new() 和 make() 。但是对于初学者而言, 它们之间的区别容易让人模糊。 简单总结之间的区别就一句话,new 只分配内存, make 用于 slice,map,和channel 的初始化。

一、new

在这里插入图片描述

1. 理解 new

C++ 当中 new 一片内存,将会调用构造函数进行初始化,但是在 gonew 一片内存只是将其设置为零值, 并且返回它的地址,一个类型为 *T 的值
go 语言当中没有 C++ 构造函数一类的说法,我们可以用 C 语言来描述 gonew 的过程:

T *t = (T*)malloc(sizeof(T));
memset(t, 0, sizeof(T));

但是上诉的描述并非完全正确, 在 go 语言当中零值对于不同的类型有不同的定义,例如 bool 类型的零值是 false, int 类型的零值是 0, 任意指针类型的零值是 nil ,string 类型的零值是空字符等

pInt := new(int) // pInt, *int类型, 指向了一个匿名的 int 变量
fmt.Println(*pInt)	// 0
*pInt = 3
fmt.Println(*pInt)  // 3

2. 函数返回局部变量和new

然而 new 创建一个变量和普通变量声明语句创建变量没有什么区别,例如函数返回局部变量地址和返回一个 new 的匿名变量的地址一样,其变量的空间都不是栈区,而是在堆区,所以说 go 中的 new 函数从一定程度上来讲只是一个语法糖,不是一个新的基础概念。
下面的 两个newInt 函数有着相同的意义

func newInt() *int {
	return new(int)
}

func newInt() *int{
	var value int
	return &value
}

通过上面我们可以得出一个结论:如果一个局部变量在函数返回后仍然被使用,这个变量会从heap,而不是stack中分配内存

3. new 大小为 0 的内存

go 语言中使用 new 的时候我们还需要注意一种情况就是 new 出来的类型都是空,也就是说类型的大小是0, 例如 new 一个 struct{}[0]int 的类型,可能有相同的地址(依赖具体的语言实现)。(译注:请谨慎使用大小为0的类型,因为如果类型的大小位0好话,可能导致Go语言的自动垃圾回收器有不同的行为,具体请查看runtime.SetFinalizer函数相关文档)

二、make

在这里插入图片描述

1. 了解 slice

type slice struct {
	array unsafe.Pointer
	len int
	cap int
}

在这里插入图片描述
slice 的结构体由3部分构成,Pointer 是指向一个数组的指针,len 代表当前切片的长度,cap 是当前切片的容量。

2. 理解make

内建函数make(T, args) 和 new(T) 不一样。make 函数主要用来创建 slice,map,channel的对象,并且返回一个初始化的值(并非置为零值),返回值的类为T的值,而并非指向它的指针。

  • slice(切片): size指定了其长度。该切片的容量等于其长度。切片支持第二个整数实参可用来指定不同的容量;它必须不小于其长度,因此 make([]int, 0, 10) 会分配一个长度为0,容量为10的切片
  • map(映射):初始分配的创建取决于size,但产生的映射长度为0。size可以省略,这种情况下就会分配一个小的起始大小。
  • channel(通道):通道的缓存根据指定的缓存容量初始化。若 size为零或被省略,该信道即为无缓存的(07 - 获取URL, 并发 goroutine和channel有通道类型的初步介绍)。

不同方式分配一个切片,长度为0,容量为10

var pArray *[]int = new([]int)  // 分配了切片类型, *pArray = nil
var pSlice []int = make([]int, 0, 10) // 分配一个长度为0,容量为10的切片类型

// 这个方式是最鸡巴蛋疼的方式
var p *[]int = new([]int)
*p = make([]int, 0, 10)

// 编程中,最适合 go 的做法的make分配
p := make([]int, 0, 10)

总结

  • 理解 newmake
  • 关注函数返回局部变量的可行性
  • new 一个大小为 0 的用法和注意事项
  • make 使用的三种方式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值