首页 > 其他分享 >Go 语言 new 和 make 关键字的区别

Go 语言 new 和 make 关键字的区别

时间:2023-04-04 14:25:23浏览次数:49  
标签:slice int make 类型 Go new fmt

原文链接: Go 语言 new 和 make 关键字的区别

本篇文章来介绍一道非常常见的面试题,到底有多常见呢?可能很多面试的开场白就是由此开始的。那就是 new 和 make 这两个内置函数的区别。

其实这个问题本身并不复杂,简单来说就是,new 只分配内存,而 make 只能用于 slice、map 和 chan 的初始化,下面我们就来详细介绍一下。

new

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 函数为变量分配内存空间:

p1 := new(int)
fmt.Printf("p1 --> %#v \n ", p1) //(*int)(0xc42000e250) 
fmt.Printf("p1 point to --> %#v \n ", *p1) //0

var p2 *int
i := 0
p2 = &i
fmt.Printf("p2 --> %#v \n ", p2) //(*int)(0xc42000e278) 
fmt.Printf("p2 point to --> %#v \n ", *p2) //0

上面的代码是等价的,new(int) 将分配的空间初始化为 int 的零值,也就是 0,并返回 int 的指针,这和直接声明指针并初始化的效果是相同的。

当然,new 函数不仅能够为系统默认的数据类型分配空间,自定义类型也可以使用 new 函数来分配空间,如下所示:

type Student struct {
   name string
   age int
}
var s *Student
s = new(Student) //分配空间
s.name = "zhangsan"
fmt.Println(s)

这就是 new 函数,它返回的永远是类型的指针,指针指向分配类型的内存地址。需要注意的是,new 函数只会分配内存空间,但并不会初始化该内存空间。

make

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

其函数签名如下:

源码

// 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:
// Slice: The size specifies the length. The capacity of the slice is
// equal to its length. A second integer argument may be provided to
// specify a different capacity; it must be no smaller than the
// length, so make([]int, 0, 10) allocates a slice of length 0 and
// capacity 10.
// Map: An empty map is allocated with enough space to hold the
// specified number of elements. The size may be omitted, in which case
// a small starting size is allocated.
// Channel: The channel's buffer is initialized with the specified
// buffer capacity. If zero, or the size is omitted, the channel is
// unbuffered.
func make(t Type, size ...IntegerType) Type

通过上面的代码可以看出 make 函数的 t 参数必须是 slice、map 和 chan 中的一个,并且返回值也是类型本身。

使用

下面用 slice 来举一个例子:

var s1 []int
if s1 == nil {
    fmt.Printf("s1 is nil --> %#v \n ", s1) // []int(nil)
}

s2 := make([]int, 3)
if s2 == nil {
    fmt.Printf("s2 is nil --> %#v \n ", s2)
} else {
    fmt.Printf("s2 is not nill --> %#v \n ", s2)// []int{0, 0, 0}
}

slice 的零值是 nil,但使用 make 初始化之后,slice 内容被类型 int 的零值填充,如:[]int{0, 0, 0}

map 和 chan 也是类似的,就不多说了。

总结

通过以上分析,总结一下 new 和 make 主要区别如下:

  1. make 只能用来分配及初始化类型为 slice、map 和 chan 的数据。new 可以分配任意类型的数据;
  2. new 分配返回的是指针,即类型 *Type。make 返回类型本身,即 Type
  3. new 分配的空间被清零。make 分配空间后,会进行初始化;

以上就是本文的全部内容,如果觉得还不错的话欢迎点赞转发关注,感谢支持。

标签:slice,int,make,类型,Go,new,fmt
From: https://www.cnblogs.com/golandhome/p/17286226.html

相关文章

  • MongoDB-如何将BSON文档转换为人类可读的格式
    二进制Javascript对象表示法(BSON)是一种以二进制编码串行化的JSON文档。JSON更容易理解,因为它是人类可读的,但与BSON相比,它支持的数据类型更少。BSON已经被扩展,可以添加一些可选的非json原生数据类型,比如日期和二进制数据。MongoDB在内部和网络上以BSON格式存储数据。mongodump生......
  • golang CVE-2016-2183漏洞,https需要添加tls设置加密算法CipherSuites白名单,将弱加密算
    golangCVE-2016-2183漏洞,https需要添加tls设置加密算法白名单,将弱加密算法DES和3DES去掉。服务端样例代码packagemainimport("crypto/tls""fmt""net/http")funchandler(writerhttp.ResponseWriter,request*http.Request){fmt.Fprintf(wri......
  • The role of local toxicity testing in evaluating new drugs
    Aseriesoftoxicitystudiesarerequiredtorevealthepossibletoxicreactionsofdrugsbeforeclinicalapplicationandtoensurethesafetyandeffectivenessofclinicaluse.Localtoxicitytestisanintegralpartoftoxicologyresearch,whichisdesi......
  • Typora配置PicGo时,提示Failed to fetch
    两者配置的端口不一致造成的打开Typora,选择文件-偏好设置-图像-验证图片上传选项,点击验证图片上传选项会提示错误:Failedtofetch,此时可以发现typora中设置的上传端口为366771.先检查监听端口是否一致打开PigGo,选择PicGo设置-设置server,会发现监听端口为36678修改监听接口......
  • cmake string example
    string(CONCATresult${var1}"/how")string(FIND${var1}"targetPattern"foundResultIndex)if(${foundResultIndex}GREATER_EQUAL0)endif()string(LENGTH<string><output_variable>)https://cmake.org/cmake/help/lates......
  • docker 部署mongoDB集群与读写分离
    一.生成key文件需要注意集群中所有机器都需要用同一个文件,否则会出现验证失败的情况#生成keyopensslrand-base64756>/data/volume/mongodb/configdb/mongo.key#设置访问权限chmod400/data/volume/mongodb/configdb/mongo.key 二.启动MongoDB的docker容器d......
  • cmake get_filename_component
    get_filename_component(<var><FileName><mode>[BASE_DIR<dir>]var:outputValueFileName:inputValuemodeDIRECTORY=DirectorywithoutfilenameNAME=FilenamewithoutdirectoryEXT=Filenamelongestextension......
  • (转)Go 语言中的类型断言是什么?
    原文:https://juejin.cn/post/6844904153056034823TypeAssertionTypeAssertion(中文名叫:类型断言),通过它可以做到以下几件事情检查i是否为nil检查i存储的值是否为某个类型具体的使用方式有两种:第一种:t:=i.(T)复制代码这个表达式可以断言一个接口对象(i)里不是nil......
  • Webgoat学习笔记
    Webgoat学习笔记Webgoat分为简单版和开发版,具体版本及安装方法详见:https://github.com/WebGoat/WebGoat本机环境为:Windows+Tomcat,故下载war包,自动解压缩进行部署。war下载地址:https://github.com/WebGoat/WebGoat/releases/    参考链接:Webgoat学习笔记:http://www.tui......
  • Django笔记十五之in查询及date日期相关过滤操作
    这一篇介绍关于范围,日期的筛选inrangedateyearweekweekdayquarterhour1、inin对应于MySQL中的in操作,可以接受数组、元组等类型数据作为参数:Blog.objects.filter(id__in=[1,2,3])对应的SQL是:select*fromblog_blogwhereidin(1,2,3);字符串也可以作......