#### 一、var、make、new、:=的使用习惯:
1.使用make(),来初始化slice,map 和channel 。
2.大多数场合,类型明确的场合下,使用短变量声明方式:=。
3.当使用文字方式初始化一个变量,并且需要指明类型时,使用var变量声明方式。
4.避免使用new(),除非你需要一个指针变量。
注意点:
make 返回值是:引用类型本身。
new 返回值:指向类型的指针。
#### 二、详细对比:
##### ** new **
###### 定义:
func new(Type) *Type
###### 特点:
1. 分配内存。内存里存的值是对应类型的零值。
2. 只有一个参数。参数是分配的内存空间所存储的数据类型,Go语言里的任何类型都可以是new的参数,比如int, 数组,结构体,甚至函数类型都可以。
3. 返回的是指针。
###### 例子:
```
// 方式1
ptr := new(T)
// 方式2
var t T
ptr := &t
```
上面两种赋值方式是等价的。
###### 注意点:
* Go的new分配的内存可能在栈(stack)上,可能在堆(heap)上。
* Go的new分配的内存里的值是对应类型的零值,不能显示初始化指定要分配的值。
##### ** make **
###### 定义:
func make(t Type, size ...IntegerType) Type
###### 特点:
1.分配和初始化内存。
2.只能用于slice, map和chan这3个类型,不能用于其它类型。 如果是用于slice类型,make函数的第2个参数表示slice的长度,这个参数必须给值。
3.返回的是原始类型,也就是slice, map和chan,不是返回指向slice, map和chan的指针。
###### 例子:
```
var c chan int //声明管道类型变量c,此时c还是nil,不可用;
fmt.Printf("%#v \n",c) //(chan int)(nil)
c = make(chan int)
fmt.Printf("%#v", c) //(chan int)(0xc000062060)
声明管道类型变量c,此时c还是nil,不可用;
通过make来分配内存并初始化,c就获得了内存可以使用了。
```
make 是分配内存并初始化,初始化并不是置为零值。
与new一样,它的第一个参数也是一个类型,但是不一样的是,make返回的是传入的类型,而不是指针!
##### 问题理解:
1.为什么针对slice, map和chan类型专门定义一个make函数?
答案:这是因为slice, map和chan的底层结构上要求在使用slice,map和chan的时候必须初始化,如果不初始化,那slice,map和chan的值就是零值,也就是nil
** nil特性:**
* map如果是nil,是不能往map插入元素的,插入元素会引发panic 。
* chan如果是nil,往chan发送数据或者从chan接收数据都会阻塞。
* slice会有点特殊,理论上slice如果是nil,也是没法用的。但是append函数处理了nil slice的情况,可以调用append函数对nil slice做扩容。但是我们使用slice,总是会希望可以自定义长度或者容量,这个时候就需要用到make。
2.可以用new来创建slice, map和chan么?
答案:可以。
参考代码:
```
package main
import "fmt"
func main() {
a := *new([]int)
fmt.Printf("%T, %v\n", a, a==nil) // []int, true
b := *new(map[string]int)
fmt.Printf("%T, %v\n", b, b==nil) // map[string]int, true
c := *new(chan int)
fmt.Printf("%T, %v\n", c, c==nil) // chan int, true
}
```
虽然new可以用来创建slice, map和chan,但实际上并没有卵用,因为new创建的slice, map和chan的值都是零值,也就是nil。这3种类型如果是nil,就出现上面介绍nil特性了,无法使用。
3.为什么slice是nil也可以直接append?
答案:对于nil slice,append会对slice的底层数组做扩容,通过调用mallocgc向Go的内存管理器申请内存空间,再赋值给原来的nil slice。
slice用make创建的时候,如果指定的长度len>0,则make创建的slice下标索引从0到len-1的值都是对应slice里元素类型的零值。参考下例:
```
package main
import "fmt"
func main() {
s := make([]int, 2, 3)
fmt.Println(s) // [0 0]
}
```
参考文档:
[golang:var、new、make区别及使用](https://www.zhihu.com/question/446317882/answer/2245768201)
[golang:var、new、make区别及使用](https://blog.csdn.net/qq_43778308/article/details/115839978)
有疑问加站长微信联系(非本文作者))