一.简单说明

方法 作用 作用对象 返回值
new 分配内存 值类型和用户定义的类型 初始化为零值,返回指针
make 分配内存 内置引用类型(map,slice,channel) 初始化为零值,返回引用类型本身

1.1 new的主要特性

new是内建函数,可以参考如下代码定义:

func new(Type) *Type

内建函数new用来分配内存,它的第一个参数是一个类型,不是一个值,它的返回值是一个指向新分配类型零值得指针。

根据上述的描述,可以自己实现一个类型new的功能:

func newInt() *int {
var i int
return &i
} someInt := newInt()

这个函数的功能和somInt := new(int)一模一样,所以我们在定义new开头的函数时,出于约定也应该返回类型的指针。

1.2 make的主要特性

make也是内建函数,它的定义比new多了一个参数,返回值也不同。可以参考如下的代码定义:

func make(Type, size IntegerType) Type

make是用来初始化map,slice,channel这几种特定类型的。编译过程中,用make去初始化不同的类型会调用不同的底层函数:

  • 1.初始化map,调用runtime.makemap
  • 2.初始化slice,调用runtime.makeslice
  • 3.初始化channel,调用runtime.makechan

接下来了解下函数的源码:

  • runtime.makemap
// path: src/runtime/map.go
func makemap(t *maptype, hint int, h *hmap) *hmap {
...
// 初始化 Hmap
if h == nil {
h = new(hmap)
} // 生成 hash 种子
h.hash0 = fastrand() // 计算 桶 的数量
B := uint8(0)
for overLoadFactor(hint, B) {
B++
}
h.B = B
if h.B != 0 {
var nextOverflow *bmap // 创建 桶
h.buckets, nextOverflow = makeBucketArray(t, h.B, nil)
...
}
return h
}
  • runtime.makeslice
// path: src/runtime/slice.go
func makeslice(et *_type, len, cap int) unsafe.Pointer {
// 计算占用空间和是否溢出
mem, overflow := math.MulUintptr(et.size, uintptr(cap)) // 一些边界条件处理
if overflow || mem > maxAlloc || len < 0 || len > cap {
mem, overflow := math.MulUintptr(et.size, uintptr(len))
if overflow || mem > maxAlloc || len < 0 {
// panic: len 超出范围
panicmakeslicelen()
}
// panic: cap 超出范围
panicmakeslicecap()
} return mallocgc(mem, et, true)
}
  • runtime.makechan
// path: src/runtime/chan.go
func makechan(t *chantype, size int) *hchan {
...
var c *hchan // 针对不同情况下对 channel 实行不同的内存分配策略
switch {
case mem == 0:
// 无缓冲区,只给 hchan 分配一段内存
c = (*hchan)(mallocgc(hchanSize, nil, true))
c.buf = c.raceaddr()
case elem.ptrdata == 0:
// channel 不包含指针,给 hchan 和 缓冲区分配一段连续的内存
c = (*hchan)(mallocgc(hchanSize+mem, nil, true))
c.buf = add(unsafe.Pointer(c), hchanSize)
default:
// 单独给 hchan 和 缓冲区分配内存
c = new(hchan)
c.buf = mallocgc(mem, elem, true)
} // 初始化 hchan 的内部字段
c.elemsize = uint16(elem.size)
c.elemtype = elem
c.dataqsiz = uint(size)
...
}

1.3 总结

make相对于new来说,做的事情更多,new只是开辟了内存空间, make为更加复杂的数据结构开辟内存空间并对一些字段进行初始化

Go语言new和make的区别的更多相关文章

  1. C、C++、C#、Java、php、python语言的内在特性及区别

    C.C++.C#.Java.PHP.Python语言的内在特性及区别: C语言,它既有高级语言的特点,又具有汇编语言的特点,它是结构式语言.C语言应用指针:可以直接进行靠近硬件的操作,但是C的指针操作 ...

  2. js课程 3-10 js中字符串函数数组函数和其它语言中对应函数的区别和联系是什么

    js课程 3-10  js中字符串函数数组函数和其它语言中对应函数的区别和联系是什么 一.总结 一句话总结:js中是对象点方法的形式,这些方法都是对象的方法,而在php.java中却不是这样. 1.j ...

  3. C程序设计语言--指针和引用的区别

    在看了一篇文章以后,http://coolshell.cn/articles/7992.html,说的是C和C++之间的缺陷,当然这篇文章说的非常高深了.所以就找了一些资料,分析了这两者的区别 在&l ...

  4. C语言几个输入函数的区别(史上最详细)

    The difference of the string and the character(char): 字符串是一个带有""的字符序列如 "I fuck xuqian ...

  5. C语言realloc,malloc,calloc的区别【转载】

    转载自:http://www.cnblogs.com/BlueTzar/articles/1136549.html 三个函数的申明分别是: void* realloc(void* ptr, unsig ...

  6. 动态样式语言Sass&Less介绍与区别

    一. Sass/Scss&Less是什么? Sass (Syntactically Awesome Stylesheets)是一种动态样式语言,语法跟css一样(但多了些功能),比css好写, ...

  7. C语言i++和++i的区别和指针*(a++)和*(++a)的区别

    i++ :先引用后增加++i :先增加后引用i++ :先在i所在的表达式中使用i的当前值,后让i加1 ++i :让i先加1,然后在i所在的表达式中使用i的新值 一.c语言中i++和++i的运行效果是不 ...

  8. c语言return与exit的区别

    2013-09-0918:54:33 exit函数在头文件stdlib.h中,函数原型: void exit(int status); exit(0) 正常运行程序并退出程序. exit(1) 非正常 ...

  9. C语言形参和实参的区别(非常详细)

    如果把函数比喻成一台机器,那么参数就是原材料,返回值就是最终产品:从一定程度上讲,函数的作用就是根据不同的参数产生不同的返回值.这一节我们先来讲解C语言函数的参数,下一节再讲解C语言函数的返回值.C语 ...

  10. C语言历史与C++的区别

    前期演变: C语言的前身是1967年由Martin Richards为开发操作系统和编译器而提出的两种高级程序设计语言BCPL和B.BCPL.Ken Thompson在BCPL的基础上,提出了新的功能 ...

随机推荐

  1. js 时间转时间戳

    前言 有时候我们用时间插件,选择好时间后,需要把日期格式转化为时间戳,再传到后台 时间转时间戳 let time = Math.floor(new Date("2014-04-23 18:5 ...

  2. composer init

    $ composer init Do not run Composer as root/super user! See https://getcomposer.org/root for details ...

  3. 文件转十六进制出现转义字符直接通过ASCII码逐字符展开的问题与修复

    近日工作中遇到某品牌电子签章系统生成的PDF文件若直接使用十六进制查看器打开,会出现转义字符被直接以ASCII编码转换为16进制字符串的问题,导致提取的文件无法匹配ASN.1格式,无法进一步对签章有效 ...

  4. 【SpringCloud】SpringCloud config分布式配置中心

    SpringCloud config分布式配置中心 概述 分布式系统面临的---配置问题 微服务意味着要将单体应用中的业务拆分成一个个子服务 ,每个服务的粒度相对较小,因此系统中会出现大量的服务.由于 ...

  5. Kratos 下载与安装

    前置条件 请确保已经安装好 go git protoc 然后获取 kratos 工具 go get -u github.com/go-kratos/kratos/tool/kratos 验证是否安装成 ...

  6. Pycharm两种快速激活方式(附最新激活码和插件)

    小张的Pycharm最近弹出提示框 Your license has expired提示过期....纳尼!!!! 是不是看到这个也很头疼,.于是我就在想有没有一种方式可以让他永久免费的,于是小张从网上 ...

  7. 基于源码分析 HikariCP 常见参数的具体含义

    HikariCP 是目前风头最劲的 JDBC 连接池,号称性能最佳,SpringBoot 2.0 也将 HikariCP 作为默认的数据库连接池. 要想用好 HikariCP,理解常见参数的具体含义至 ...

  8. python爬虫爬取小说网站

    项目场景: 利用python爬取某小说网站,主要爬取小说名字,作者,类别,将其保存为三元组形式:(xxx, xxx, xxx)并将其保存至excel表格中.本文从爬取目的到爬取的各步骤都尽量详细的去复 ...

  9. 【HUST】网安|多媒体数据安全实验|LSB隐写和DCT域JSTEG+F4+F5隐写及检测

    文章目录 LSB空域隐写 原理 值对现象原理 实验内容 DCT域隐写 JSteg F4 F5 代码仓库:代码.嵌入提取使用的图像.jpeg_tool库.实验报告_Gitee. 实验环境:MATLAB ...

  10. 【记录】Opencv+LibTorch安装

    环境Ubuntu20.04. [Opencv]源码编译:Linux系统下opencv3.4.1安装教程 [LibTorch]下载已编译版本:在Ubuntu下安装LibTorch [磁盘空间不足]vmw ...