Go语言(golang)中,make和new有什么区别呢? |
您所在的位置:网站首页 › cache地址结构和存储结构有什么区别呢 › Go语言(golang)中,make和new有什么区别呢? |
前言 在Go语言中,初始化数据结构的时候,可能会用到2个内置函数:new和make。 new和make都可以用来分配内存,那他们有什么区别呢?在写代码过程中,对于new和make的最佳实践又是什么呢? new是什么我们先看看new的官方定义: func new(Type) *TypeThe 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. 从官方定义里可以看到,new有以下几个特点: 分配内存。内存里存的值是对应类型的零值。只有一个参数。参数是分配的内存空间所存储的数据类型,Go语言里的任何类型都可以是new的参数,比如int, 数组,结构体,甚至函数类型都可以。返回的是指针。以下代码是等价的,可以认为new(T)是 var t T; &t 的语法糖。 注意:Go里的new和C++的new是不一样的: Go的new分配的内存可能在栈(stack)上,可能在堆(heap)上。C++ new分配的内存一定在堆上。Go的new分配的内存里的值是对应类型的零值,不能显示初始化指定要分配的值。C++ new分配内存的时候可以显示指定要存储的值。Go里没有构造函数,Go的new不会去调用构造函数。C++的new是会调用对应类型的构造函数。make是什么我们再看看make的官方定义: func make(t Type, size ...IntegerType) TypeThe 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. For example, make([]int, 0, 10) allocates an underlying array of size 10 and returns a slice of length 0 and capacity 10 that is backed by this underlying array. 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. 从官方定义里可以看到,make有如下几个特点: 分配和初始化内存。 只能用于slice, map和chan这3个类型,不能用于其它类型。如果是用于slice类型,make函数的第2个参数表示slice的长度,这个参数必须给值。 返回的是原始类型,也就是slice, map和chan,不是返回指向slice, map和chan的指针。几个问题这里来回答几个使用new和make过程中的常见问题,从简单到复杂: 为什么针对slice, map和chan类型专门定义一个make函数?答案:这是因为slice, map和chan的底层结构上要求在使用slice,map和chan的时候必须初始化,如果不初始化,那slice,map和chan的值就是零值,也就是nil。我们知道: map如果是nil,是不能往map插入元素的,插入元素会引发panic chan如果是nil,往chan发送数据或者从chan接收数据都会阻塞 slice会有点特殊,理论上slice如果是nil,也是没法用的。但是append函数处理了nil slice的情况,可以调用append函数对nil slice做扩容。但是我们使用slice,总是会希望可以自定义长度或者容量,这个时候就需要用到make。 可以用new来创建slice, map和chan么?答案:可以。代码可以参考如下示例: 输出结果是: 虽然new可以用来创建slice, map和chan,但实际上并没有卵用,因为new创建的slice, map和chan的值都是零值,也就是nil。这3种类型如果是nil,那遇到的问题我们在上面第一个问题已经解答过了,这里不再赘述。 为什么slice是nil也可以直接append?答案:对于nil slice,append会对slice的底层数组做扩容,通过调用mallocgc向Go的内存管理器申请内存空间,再赋值给原来的nil slice。 slice用make创建的时候,如果指定的长度len>0,则make创建的slice下标索引从0到len-1的值都是对应slice里元素类型的零值。参考下例:最佳实践尽量不使用new对于slice, map和chan的定义和初始化,优先考虑使用make函数开源地址本文章和代码开源在:https://github.com/jincheng9/go-tutorial,也欢迎大家关注公众号:coding进阶,学习更多Go知识。 References |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |