golang中var、make、new、:= 的使用

shensi · · 2369 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

#### 一、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)

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2369 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传