golang中new与make的区别

news2024/11/26 10:25:48

new和make

new

// The new built-in function allocates memory. The first argument 
// is a type,not a value, and the value returned is a pointer to a
// newly // allocated zero value of that type.
func new(Type) *Type

对于官方是这么解释new的:这个内置函数功能是分配内存。第一个参数是一个自定义类型,并不是一个值,返回值为一个指向新分配好的内存空间的一个指定类型指针,并且这个内存空间会被清零(也就是变为该类型的零值)。

使用new初始化

至于使用new进行初始化,根据语言规范:The built-in function new takes a type T and returns a value of type *T. The memory [pointed to] is initialized as described in the section on initial values.因为go中的函数不能被重载,并且这不是可变参数,所以无法传递任何初始化数据。 取而代之的是,go将使用对类型和任何成员字段适当的任何0版本进行初始化。

零值

go语言总共分为四大类型:基本数据类型、复杂数据类型、引用数据类型和接口类型。零值是指基本数据类型和指针的初始值。
数值型零值为0、string的零值为""、bool的零值为false、指针的零值为nil

使用示例(new也可以为数组分配内存)

 a := new(int)
 fmt.Printf("类型为:%T, 值为:%v\n", a, a)
 fmt.Printf("类型为:%T, 值为:%v\n", *a, *a)
 b := new(string)
 fmt.Printf("类型为:%T, 值为:%v\n", b, b)
 fmt.Printf("类型为:%T, 值为:%v\n", *b, *b)
 c := new(*int)
 fmt.Printf("类型为:%T, 值为:%v\n", c, c)
 fmt.Printf("类型为:%T, 值为:%v\n", *c, *c)
 
 运行结果:
 类型为:*int, 值为:0xc0000a6058
 类型为:int, 值为:0               
 类型为:*string, 值为:0xc000088220
 类型为:string, 值为:             
 类型为:**int, 值为:0xc0000ca020  
 类型为:*int, 值为:<nil>  

new(struct)和&struct{}区别

因为struct{}这种操作可以对类型进行初始化,并且基于上述new的理解之后就会发现&struct{}new(struct)其实这两种声明方式几乎没有区别。但我们在项目中经常会使用到这两种操作,就自然会想这两者的区别(跟本人一样)。

在我调查了一些资料后,我个人觉得他们唯一的区别就在于new只能声明一个零值的该类型的指针并返回,但是&struct{}可以在声明的同时进行初始化操作。

func main(){
	A := new(struct) // 只能返回一个struct的指针
	B := &struct{Id:1,Name:"张三"} // 可以返回一个带有默认值的struct的指针
}

上述例子就很好的说明了这个问题。

小结

new只能开辟单个空间,不能为引用类型开辟多个空间。并且new是对类型进行内存的开辟,返回一个指向该内存空间的指针类型。如果使用new去初始化引用数据类型,不是很合适(当然,new一个对象还是可以的)。因此就需要用到另一个内置函数make。

make

// The make built-in function allocates and initializes an object of type // slice, map, or chan (only). Like new, the first argument is a type, not a // value. Unlike new, make's return type is the same as the type of its // argument, not a pointer to it. The specification of the result depends on // the type:
func make(t Type, size ...IntegerType) Type

对于官方是这么解释make的:该函数功能是分配内存并且初始化一个切片(slice/map/channel)类型的对象。相比较内置函数new而言,make的第一个参数也是一个自定义类型,不是一个值。但make的返回类型是一个和他传入的自定义参数类型完全相同的类型。并不是一个指针去指向这个新开辟的内存空间。

make 也是用于内存分配的,但是和 new 不同,它只用于 chan、map 以及 slice 的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。

简述make的初始化(slice/map/channel)

在这里插入图片描述

make在对slice/map/channel这三种类型进行初始化时,在编译初期阶段,go语言就已经将代表make关键字的OMAKE节点根据参数类型的不同转换成了OMAKESLICE、OMAKEMAP、OMAKECHAN三种不同类型的节点。这些不同的节点最终会调用不同的运行时函数来初始化数据结构。

使用示例

var a []int
fmt.Println(a[0])
// 运行结果
panic: runtime error: index out of range [0] with length 0

如果不对切片进行初始化,就无法使用

 var a []int
 a = make([]int, 1)
 fmt.Println(a[0])

mapchan也同理。切片需要指定长度大小,容量可以自动扩容。如果下标超出指定的长度也会出现数组越界的情况。但是map不会发生该情况。即使初始化map容量为0map底层也会自动进行扩容。对于channel来说初始化容量就是初始化缓冲区长度。

总结:

makenew共同点都是可以开辟内存空间,给变量分配内存。
不同点在于:

  • 两者的作用类型不同,newint、string、数组分配内存,makeslice、map、channel分配内存。
  • 两者的返回值不同,new的返回值类型为一个指向新分配好的内存空间的一个指定类型指针。而make的返回值类型为它本身。
  • new分配的内存空间会被清零。make分配空间之后会被初始化。
  • new分配的内存空间不一定会在堆上分配,当指向这个内存空间的指针变量作用域不会在作用域外被使用,或者说这个变量只使用一次就不再使用。那么new分配的内存空间就会在当前的函数栈中随着栈的结束而被销毁。make则会在栈上开辟一块栈帧,栈帧里面有栈的指针和栈顶指针,分别记录栈帧的空间,随着函数的执行完毕,栈里的栈帧就会自动清空。

简单的说,new只分配内存,make用于slice,map,和channel的初始化,并且不返回指针。要获得一个显式的指针,使用new进行分配,或者显式地使用一个变量的地址。

参考资料

go语言中文网
深入学习golang

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/153866.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(6)go-micro微服务consul配置、注册中心

文章目录一 Consul介绍1. 注册中心Consul基本介绍2.注册中心Consul关键功能3.注册中心Consul两个重要协议二 Consul安装1.使用docker拉取镜像三 Config配置四 Consul代码编写1.设置consul配置中心2.获取consul配置中心的数据3.consul可视化界面数据编写4. main.go代码编写五 最…

微信小程序-页面导航

小程序实现页面导航的两种方式 声明式导航(tabBar 页面&#xff0c;在app.json中配置) 在页面上声明一个<navigator>导航组件通过点击<navigator> 组件实现页面跳转 app.json中 "tabBar": {"list": [{"pagePath": "pages/home…

【胖虎的逆向之路】02——Android整体加壳原理详解实现

【胖虎的逆向之路】(02)——Android整体加壳原理详解&实现 Android Apk的加壳原理流程及详解 文章目录【胖虎的逆向之路】(02)——Android整体加壳原理详解&实现前言一、加壳前的知识储备1. Android 应用的启动流程2. Android 应用的安装3. Android应用的启动流程&…

09-JAVA四种引用类型?

在JDK1.2版之后&#xff0c;Java对引用的概念进行了扩充&#xff0c;将引用分为强引用&#xff08;Strongly Reference&#xff09;、软引用&#xff08;Soft Reference&#xff09;、弱引用&#xff08;Weak Reference&#xff09;和虚引用&#xff08;Phantom Reference&…

使用Deep Q-Network学习如何玩《飞行的小鸟》游戏

目录概述效果需要的依赖如何运行算法原理实验输入处理网络结构训练代码概述 使用DQN实现《飞行的小鸟》游戏&#xff0c;代码可修改扩展为其他游戏&#xff0c;适合学习研究用。 效果 需要的依赖 Python 2.7 or 3 TensorFlow 0.7 pygame OpenCV-Python 如何运行 运行主函数…

目标追踪综述

目标追踪综述 - 知乎目标跟踪是计算机视觉领域的一个重要问题&#xff0c;目前广泛应用在体育赛事转播、安防监控和无人机、无人车、机器人等领域。下面是一些应用的例子。 体育赛事转播 无人车 目标跟踪任务分类了解了目标跟踪的用途&#xff0c;我们接下…https://zhuanlan.z…

Java(SpringBoot)项目打包(构建)成`Docker`镜像的几种方式

前置说明 最为原始的打包方式spring-boot-maven-plugin插件jib-maven-plugin插件dockerfle-maven-plugin插件 最为原始的方式 也就是使用Docker的打包命令去打包&#xff0c;麻烦&#xff0c;我这里不多说。 spring-boot-maven-plugin插件打包 SpringBoot自己内置了一个Docker镜…

有了这些软件测试面试话术,offer想不拿到都难

软件测试是一个复杂且重要的技术岗位&#xff0c;因此&#xff0c;大多数互联网企业在面试时&#xff0c;都会严谨对待每一个面试者。而&#xff0c;作为即将去进行面试测试人来说&#xff0c;想要在面试中&#xff0c;沉着稳定地回答好面试官们提出的问题&#xff0c;前期的软…

P5 内积 -- 通讯原理

目录内积内积和傅里叶变换正交能量帕瑟瓦尔定理互能量一 内积定义&#xff1a;任意信号 内积定义为&#xff1a;如果都是实信号例&#xff1a;二 内积和傅里叶变换的关系傅里叶变换 和逆变换 本质上就是求两个函数的内积傅里叶变换傅里叶逆变换时域的内积等于频域的内积假设 则…

再获殊荣!维视智造斩获2022年度光能杯最具影响力“智造”企业奖

近日&#xff0c;由光伏行业权威媒体和机构——索比光伏网、索比咨询联合主办的2022年度“光能杯”影响力大奖榜单发布&#xff0c;维视智造凭借硬件与AI算法能力、凭借在光伏行业具有创新性的智能制造产品方案与落地的标杆案例&#xff0c;斩获“2022年最具影响力“智造”企业…

Windows下Canal.deployer-1.1.6安装部署

canal [kənl]&#xff0c;译意为水道/管道/沟渠&#xff0c;主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量数据订阅和消费 早期阿里巴巴因为杭州和美国双机房部署&#xff0c;存在跨机房同步的业务需求&#xff0c;实现方式主要是基于业务 trigger 获取增量变…

多线程之线程控制与互斥

1.线程的缺点有哪些&#xff1f; 第一点 健壮性低------ 一个线程挂了容易影响另外的线程 第二点 缺乏访问控制----- 不像进程是独立的&#xff0c;可以写时拷贝&#xff0c;线程随进随出有点危险哦 第三点 编写难度上升----- 编写一个多线程的代码和调试可比单线程难多了 ——…

strlen 的三种模拟方法

欢迎来到 Claffic 的博客 &#x1f49e;&#x1f49e;&#x1f49e; 前言&#xff1a; 在C/C 中&#xff0c;strlen函数是一种计算字符串长度的库函数&#xff0c;要模拟此函数有多种方法&#xff0c;这里总结三种模拟方法。 1. strlen 函数介绍 cplusplus - strlen strlen 函数…

正点原子-Linux嵌入式开发学习-第二期06

第十四讲&#xff1a;主频和时钟配置 分析一个芯片的时钟&#xff0c;肯定先知道它的时钟来源&#xff0c;一般来源于外部晶振&#xff0c;内部晶振很少使用 时钟来源分析 RTC的时钟并不是其他外设的晶振来源 24MHz 晶振是 I.MX6U 内核和其它外设的时钟源&#xff0c;也是我…

K8s入门

K8s入门K8s入门k8s介绍k8s功能概述k8s架构k8s核心概念服务器配置要求部署方式使用kubeadm搭建一个k8s集群所有节点安装 Docker/kubeadm/kubeletK8s入门 你好&#xff01; 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这…

84.【Vue--初刷】

vue.js(一)、vue.js简介1.简介(1).MVVM模式的实现(2).为什么要使用Vue.js(3).为什么要使用MVVC2.应用场景3.JavaScipt框架(1).JQuery :(2).Angular(3).React(4).Vue(5).Axios4.UI框架【可视化】5.JavaScript 构建工具6.三端开发(1).混合开发(Hybrid App)(2).微信小程序7.后端技…

LeetCode题解 回溯(一):77 组合;216 组合总和III

回溯 从今天开始进入回溯&#xff0c;其实此前也接触过几道使用了该思想的题目 回溯的思想是“倒退到上一个状态”&#xff0c;通常结合递归&#xff0c;解决的问题多是“从众多组合中找出符合条件的组合”的问题&#xff0c;随想录中给出了题目大纲&#xff1a; 回溯算法解决…

Linux学习笔记——ZooKeeper集群安装部署

5.8、ZooKeeper集群安装部署 5.8.1、简介 Zookeeper是一个分布式的、开放源码的分布式应用程序协调服务&#xff0c;是Hadoop和HBase的重要组件。它是一个为分布式应用提供一致性服务的软件&#xff0c;提供的功能包括&#xff1a;配置维护、域名服务、分布式同步、组服务等。…

CHAPTER 2 Docker镜像

docker镜像2.1 docker image 获取2.1.1 命令格式&#xff08;pull&#xff09;2.1.2 层(layer)2.1.3 镜像重名2.2 查看镜像信息&#xff08;ls&#xff0c;tag&#xff0c;inspect&#xff0c;history&#xff09;2.2.1 使用images命令列出镜像&#xff08;ls&#xff09;2.2.2…

uni-app:小程序开发总结

内容持续更新中~~~&#x1f618;uniapp项目起步:工具下载在Dcloud 官网上下载 HBuilderX 开发工具,以及微信开发者工具.(同时你要在微信开发者文档进行小程序注册,拿到 ID, HBuilderX 和 微信开发者工具 你都要进行注册登录)项目创建我们可以通过HBuilderX 来进行基础版的项目创…