当前位置: 首页 > news >正文

Go 面试系列: new 和 make有什么不同之处呢?

Go 面试系列: new 和 make有什么不同之处呢?

前言

现在的大厂都开始慢慢使用Go语言了,例如字节已经把Go作为后端开发的主要编程语言。但是Go的面试题总结的比较少,于是打算开启这个专栏,一起学习一起进步。

在 Go 语言中,有两个比较雷同的内置函数,分别是 newmake 方法,其主要用途都是用于分配相应类型的内存空间。

看上去 newmake 都是分配内存的,那他们有什么区别呢?这个细节点也成为了不少 Go 语言工程师的面试题之一,值得大家一看。

在这篇文章中我们将来解答这个问题。

基本特性

make

在 Go 语言中,内置函数 make 仅支持 slicemapchannel 三种数据类型的内存创建,其返回值是所创建类型的本身,而不是新的指针引用

函数签名如下:

func make(t Type, size ...IntegerType) Type

具体使用示例:

func main() {
 v1 := make([]int, 1, 5)
 v2 := make(map[int]bool, 5)
 v3 := make(chan int, 1)
    
 fmt.Println(v1, v2, v3)
}

在代码中,我们分别对三种类型调用了 make 函数进行了初始化。你会发现有的入参是有多个长度指定,有的没有。

这块的区别主要是长度(len)和容量(cap)的指定,有的类型是没有容量这一说法,因此自然也就无法指定。

输出结果:

[0] map[] 0xc000044070

有一个细节点要注意,调用 make 函数去初始化切片(slice)的类型时,会带有零值,需要明确是否需要。

见过不少的小伙伴在这上面踩坑。

new

在 Go 语言中,内置函数 new 可以对类型进行内存创建和初始化。其返回值是所创建类型的指针引用,与 make 函数在实质细节上存在区别。

函数签名如下:

func new(Type) *Type

具体使用示例:

type T struct {
 Name string
}

func main() {
 v := new(T)
 v.Name = "Viper"
}

从上面的例子的效果来看,是不是似曾相似?其实与下面这种方式的一样的:

func main() {
 v := T{}
 v.Name = "Viper"
}

输出结果均是:

&{Name:Viper}

其实 new 函数在日常工程代码中是比较少见的,因为他可被替代。

一般会直接用快捷的 T{} 来进行初始化,因为常规的结构体都会带有结构体的字面属性:

func NewT() *T {
 return &T{Name: "Viper"}
}

这种初始化方式更方便。

区别在哪里

可能会有的小伙伴会疑惑一点,就是 new 函数也能初始化 make 的三种类型:

 v1 := new(chan bool)
 v2 := new(map[string]struct{})

make 函数的区别,优势是什么呢?

本质上在于 make 函数在初始化时,会初始化 slicechanmap 类型的内部数据结构,new 函数并不会。

例如:在 map 类型中,合理的长度(len)和容量(cap)可以提高效率和减少开销。

更进一步的区别:

  • make 函数:

    • 能够分配并初始化类型所需的内存空间和结构,返回引用类型的本身。
    • 具有使用范围的局限性,仅支持 channelmapslice 三种类型。
    • 具有独特的优势,make 函数会对三种类型的内部数据结构(长度、容量等)赋值。
  • new 函数:

    • 能够分配类型所需的内存空间,返回指针引用(指向内存的指针)。
    • 可被替代,能够通过字面值快速初始化。

总结

在这篇文章中,我们介绍了 Go 语言中 makenew 函数的使用,并针对其区别点进行了分析。

可能会有小伙伴疑惑,那 newmake 函数所初始化出来的内存,是分配在堆还是栈上呢?

这就涉及到 Go 语言中的 “逃逸分析” 了,如果所初始化的变量不需要在当前作用域外生存,那么理论上就不需要初始化在堆上。

相关文章:

  • Go 面试系列: Goroutine 数量是越多越好吗?设置多少会影响GC调度呢?
  • 什么是读、写扩散?
  • 一文搞定权限设计模型(RBAC,ABAC)超详细图文解析
  • 一文搞定权限管理!授权、鉴权超详细解析
  • Go 中的 JSON如何序列化和反序列化?来看看go的包怎么实现!
  • Go中如何比较两个json?深度优先搜索解决,超详细代码!
  • Go语言实现枚举方法,const和iota结合轻松实现
  • Go msgp序列化使用详解!比Json更快!面试时吊打面试官!
  • 缓存击穿了怎么办?使用singleflight轻松解决!
  • Go中优雅的获取Map元素的多种方法
  • Go中的nil是是什么?和java的null有区别吗?
  • 大厂面试必会语言:GO语言入门,看这一篇就够了
  • 无需安装!Windows11网页版来了!一键带你体验win11!
  • Go语言里如何采用面向对象编程?Go中一样能够面向对象!
  • Go 面试系列:如何比较GO中的结构体?
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • ES2017异步函数现已正式可用
  • HTTP 简介
  • JavaScript实现分页效果
  • java中的hashCode
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • PHP 的 SAPI 是个什么东西
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • 关于springcloud Gateway中的限流
  • 规范化安全开发 KOA 手脚架
  • 猫头鹰的深夜翻译:Java 2D Graphics, 简单的仿射变换
  • 巧用 TypeScript (一)
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 深度学习中的信息论知识详解
  • 树莓派 - 使用须知
  • 要让cordova项目适配iphoneX + ios11.4,总共要几步?三步
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 白色的风信子
  • 从如何停掉 Promise 链说起
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​​​​​​​​​​​​​​Γ函数
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (2.2w字)前端单元测试之Jest详解篇
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (四)Controller接口控制器详解(三)
  • (译)计算距离、方位和更多经纬度之间的点
  • (转)iOS字体
  • .gitignore文件—git忽略文件
  • .NET 4.0中的泛型协变和反变
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .NET Core WebAPI中封装Swagger配置
  • .net mvc部分视图
  • .net6解除文件上传限制。Multipart body length limit 16384 exceeded
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...