Golang make 与 new 函数的区别

这两个函数都用于分配内存,但两者之间仍然有一些差异。本文介绍它们之间的差异,以及各自的应用场景。简言之,new分配内存但不初始化内存;make分配内容并初始化内存,所谓初始化即给变量赋初始值。举例,字符串为空,整型为0,布尔变量为false。

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函数参数是类型,返回值是指针,指向该类型的内存地址,分配的内存被设为零值,即该类型的零值,就是说字符串为空,整型为0,布尔变量为false等。

下面请看示例:

package main

import (
	"fmt"
)

func main() {
	type P struct {
		Name string
		Age  int
	}

	var a *[2]int
	var s *string
	var b *bool
	var i *int
	var ps *P

	a = new([2]int)
	s = new(string)
	b = new(bool)
	i = new(int)
	ps = new(P) //structure

	fmt.Println(a, " ", *a)
	fmt.Println(s, " ", *s)
	fmt.Println(b, " ", *b)
	fmt.Println(i, " ", *i)
	fmt.Println(ps, " ", *ps)
}

输出结果:

&[0 0]   [0 0]
0xc00004c250        
0xc00001a098   false
0xc00001a0c0   0    
&{ 0}   { 0}        

上面是基本类型,下面看slice、map、Chan,new操作的结果进行对比:

package main

import (
	"fmt"
)

func main() {
	//map operation
	var mp *map[string]string
	mp = new(map[string]string)
	//*mp = make(map[string]string)
	// if previous line is omitted, it will pan "Pan: assignment to entry in nil map"
	(*mp)["name"] = "lc"
	fmt.Println((*mp)["name"])

	//slice operation
	var ms *[]string
	ms = new([]string)
	//*ms = make([]string, 5)
	// if previous line is deleted, it will "panic: runtime error: index out of range"
	(*ms)[0] = "lc"
	fmt.Println((*ms)[0])
}

我们看到slice,map,channel以及其他的引用类型初始化时为nil,nil不能被直接赋值。new也不能分配内存,还需要make分配内存。

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:
//  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.
func make(t Type, size ...IntegerType) Type

make函数返回值与参数类型一致,而不是指针,因为make仅初始化slice,map,channel等的内存,而这些类型是引用类型,不需要返回指针。请看示例:

package main

import (
	"fmt"
)

func main() {
	mm := make(map[string]string)
	mm["name"] = "lc"
	fmt.Println(mm["name"])

	mss := make([]int, 2)
	mss[0] = 100
	fmt.Println(mss[0])

	ch := make(chan int, 1)
	ch <- 100

	fmt.Println(<-ch)
}

总结

make仅用于分配并初始化slice,map,channel类型,而new能分配任何数据类型。new返回指针(Type, *Type),make返回引用(Type).另外new仅分配空间,make分配的空间之后被清空并初始化。

这里顺便说下指针与引用的区别:

  • 指针
    指针是保存另一个变量的内存地址的变量。指针需要用*操作符解引用,以访问它所指向的内存位置。

  • 引用
    引用变量是别名,即已经存在的变量的另一个名称。引用和指针一样,也是通过存储对象的地址来实现的。引用可以被认为是一个具有自动间接功能的常量指针(不要与指向常量值的指针混淆!),也就是说,编译器会为你应用*操作符。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值