golang知识点-new和make

    在编程过程当中,一定会涉及到变量的声明和使用。在golang中,对变量对声明和初始化操作有两个关键子new和make。 

    一开始学习的时候,就记不住,也没区分出来差异是什么。后面看了他人的文章才慢慢有点理解。就把自己的理解过程梳理出来。 

变量的声明

     new和make主要用于变量的声明和初始化。我们这里就先拆解出来,分两部分如何声明,如何厨师阿虎。 变量的声明我们可以通过var关键字。并且使用var在声明的时候,会给变量设置默认值。比如int类型的零值是0,string类型的零值是"",引用类型的零值是nil。

    例如:int,string类型。声明的变量能够直接拿来使用。 

var i int
var s string

i = 10
s = 'hello world'
//能够编译得过。 

   例如:引用类型,不能够直接使用。使用将会报错。 

package main
import (
 "fmt"
)
func main() {
 var i *int
 *i=10
 fmt.Println(*i)
}
//编译将会报错
//panic: runtime error: invalid memory address or nil pointer dereference

    对于引用类型的变量,我们不光要声明它,还要为它分配内容空间,否则我们的值放在哪里去呢?这就是上面错误提示的原因。

PS:对于这个内存空间,有一个自己的辅助性的理解。var在定义的时候具体的地址空间是这样的。 

9e34dcb41e322f056214092052e46e0e8d8.jpg

所以,这样当我们要使用引用类型的时候。就会出现错误。因为根本没有指向一个实际的内存空间地址。根本没办法赋值。所以这时候var定义完变量之后就需要进行初始化动作。 这样也就引出来new和make的作用。 

new

new 會自動用 zeroed value 來初始化型別,也就是字串會是"",number 會是 0,channel, func, map, slice 等等則會是 nil

另外一个重点是:new函数,返回的是一个指向该类型内存地址的指针。

func main() {
    people := new(map[string]string)  //返回的是一个指针类型。
    p := *people   //取people指针的值。
    p["name"] = "Kalan" // panic: assignment to entry in nil map  //提示这里是一个nil值。
}
//-------以下的例子说明new返回的是一个指针值-------
type Person struct {
  Name string
  Age  int
}

func main() {
    //效果一样。
    p := &Person{}    //对定义的结构题,取指针值。
    p := new(Person)  //返回的是一个指针值。
}

对于上面的问题我们如何解决呢?既然我们知道了没有为其分配内存,那么我们使用new分配一个吧。

func main() {
 var i *int
 i=new(int)  //这里就会分配一个内存空间。
 *i=10
 fmt.Println(*i)
}

//#另外一个例子
func main() {
 u:=new(user)
 u.lock.Lock()
 u.name = "张三"
 u.lock.Unlock()
 fmt.Println(u)
}
type user struct {
 lock sync.Mutex
 name string
 age int
}

PS:辅助理解的指针图

c453723a412b1fe67a6af56858cb513727e.jpg

 

make

make也是用于内存分配的,但是和new不同,它只用于chan、map以及切片的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。make不会传回来一个指针值。(因为没必要)

注意,因为这三种类型是引用类型,所以必须得初始化,但是不是置为零值,这个和new是不一样的

二者异同

所以从这里可以看的很明白了,二者都是内存的分配(堆上),但是make只用于slice、map以及channel的初始化(非零值);而new用于类型的内存分配,并且内存置为零。所以在我们编写程序的时候,就可以根据自己的需要很好的选择了。

make返回的还是这三个引用类型本身;而new返回的是指向类型的指针。

func main() {
    receiver := make(chan string) // 初始化 channel,但不回傳指標
    person := make(map[string]string)
    people := make([]string, 100) // 初始化長度為 100 的字串陣列

    //之后就可以正常使用了。
}

有需要拿到引用类型的指针的场景?

ps:在我个人的理解。在函数传递参数的时候,可以理解为传递值。对于引用类型来说,本身的值。就是一直指向“目标”的指针。所以运用到的场景应该不多。

PS:辅助理解的图(不一定正确,仅辅助自己理解)

27567d47c9fdf0d65617e47b3477849dc4f.jpg

小结

其实new不常用

所以有new这个内置函数,可以给我们分配一块内存让我们使用,但是现实的编码中,它是不常用的。我们通常都是采用短语句声明以及结构体的字面量达到我们的目的,比如:

i := 0

u := user{}

这样更简洁方便,而且不会涉及到指针这种比麻烦的操作。

  • make 用于chan  map slice 的初始化。
  • new 初始化,返回的是。一个类型的指针。

 

本篇主要内容参考引用于:

https://www.flysnow.org/2017/10/23/go-new-vs-make.html

https://studygolang.com/articles/18232

 

 

转载于:https://my.oschina.net/u/4156317/blog/3067891

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值