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

shensi · 2022-06-06 17:05:31 · 2582 次点击 · 预计阅读时间 3 分钟 · 大约8小时之前 开始浏览    
这是一个创建于 2022-06-06 17:05:31 的文章,其中的信息可能已经有所发展或是发生改变。

一、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区别及使用

golang:var、new、make区别及使用


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

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

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