golang中var、make、new的使用[转]

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

原文:https://studygolang.com/articles/35687