前言

本文主要给大家介绍了Go语言中函数new与make的使用和区别,关于Go语言中new和make是内建的两个函数,主要用来创建分配类型内存。在我们定义生成变量的时候,可能会觉得有点迷惑,其实他们的规则很简单,下面我们就通过一些示例说明他们的区别和使用,话不多说了,来一起看看详细的介绍吧。

变量的声明

var i int
var s string

变量的声明我们可以通过var关键字,然后就可以在程序中使用。当我们不指定变量的默认值时,这些变量的默认值是他们的零值,比如int类型的零值是0,string类型的零值是"",引用类型的零值是nil。

对于例子中的两种类型的声明,我们可以直接使用,对其进行赋值输出。但是如果我们换成引用类型呢?

package main
import (
"fmt"
)
func main() {
var i *int
*i=10
fmt.Println(*i)
}

这个例子会打印出什么?0还是10?。以上全错,运行的时候会painc,原因如下:

panic: runtime error: invalid memory address or nil pointer dereference

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

对于值类型的声明不需要,是因为已经默认帮我们分配好了。

要分配内存,就引出来今天的new和make。

new

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

func main() {
var i *int
i=new(int)
*i=10
fmt.Println(*i)
}

现在再运行程序,完美PASS,打印10。现在让我们看下new这个内置的函数。

// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
func new(Type) *Type

它只接受一个参数,这个参数是一个类型,分配好内存后,返回一个指向该类型内存地址的指针。同时请注意它同时把分配的内存置为零,也就是类型的零值。

我们的例子中,如果没有*i=10,那么打印的就是0。这里体现不出来new函数这种内存置为零的好处,我们再看一个例子。

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
}

示例中的user类型中的lock字段我不用初始化,直接可以拿来用,不会有无效内存引用异常,因为它已经被零值了。

这就是new,它返回的永远是类型的指针,指向分配类型的内存地址。

make

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

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

func make(t Type, size ...IntegerType) Type

从函数声明中可以看到,返回的还是该类型。

二者异同

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

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

其实new不常用

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

i:=0
u:=user{}

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

make函数是无可替代的,我们在使用slice、map以及channel的时候,还是要使用make进行初始化,然后才可以对他们进行操作。

参考

https://www.jb51.net/article/126703.htm

[转]Go语言中的make和new的更多相关文章

  1. C语言中,头文件和源文件的关系(转)

    简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析阶段 3.编译阶段,首先编译成纯汇编语句, ...

  2. C 语言中 setjmp 和 longjmp

    在 C 语言中,我们不能使用 goto 语句来跳转到另一个函数中的某个 label 处:但提供了两个函数——setjmp 和 longjmp来完成这种类型的分支跳转.后面我们会看到这两个函数在处理异常 ...

  3. c语言中的scanf在java中应该怎么表达,Scanner类。

    1 java是面向对象的语言 它没有像C语言中的scanf()函数,但是它的类库中有含有scanf功能的函数 2 java.util包下有Scanner类 Scanner类的功能与scanf类似 3 ...

  4. C语言中do...while(0)的妙用(转载)

    转载来自:C语言中do...while(0)的妙用,感谢分享. 在linux内核代码中,经常看到do...while(0)的宏,do...while(0)有很多作用,下面举出几个: 1.避免goto语 ...

  5. C语言中,定义的含义?声明的含义?它们之间的区别是什么?

    在C语言中,对于定义和声明,也许我们非常的熟悉,但不一定真正的了解! 定义的含义:所谓定义,就是创建(编译器)一个对象,为这个对象分配一块内存空间并取名,也就是我们平常所说的变量名或对象名,一旦这个名 ...

  6. C++中函数的默认参数和C语言中volatile的学习

    1.函数默认参数 1 int func(int a,int b=10) 2 { 3 return a*b; 4 } 5 6 int main() 7 { 8 int c=func(2); 9 cout ...

  7. C语言中qsort函数用法

    C语言中qsort函数用法-示例分析    本文实例汇总介绍了C语言中qsort函数用法,包括针对各种数据类型参数的排序,非常具有实用价值非常具有实用价值. 分享给大家供大家参考.C语言中的qsort ...

  8. c语言中time相关函数

    工作中遇到的函数: int seed = time(NULL); srand(seed); signal(SIGINT, stop); signal(SIGUSR1, sig_usr1); 搜time ...

  9. C语言中的static 详细分析

    转自:http://blog.csdn.net/keyeagle/article/details/6708077/ google了近三页的关于C语言中static的内容,发现可用的信息很少,要么长篇大 ...

  10. C语言中if语句

    C语言if语句后面的表达式 C语言中if关键字之后(即括号内)均为表达式. 该表达式通常是逻辑表达式或关系表达式,但也可以是其它表达式,如赋值表达式等,甚至也可以是一个变量,这些变量的值都换算成了逻辑 ...

随机推荐

  1. lnmp更改网站文件和MySQL数据库的存放目录

    购买阿里云服务器,一般建议买一个数据盘,也就是系统盘和数据盘分开,将网站文件和Mysql数据库等都保存在数据盘,即使系统盘或者环境出问题,重置系统盘和重新配置环境,都不会影响数据盘的东西. 配置好LN ...

  2. [JLOI2012]时间流逝

    Description: 你有n个食物,每个食物有\(a_i\)的价值,你每天有\(p_i\)的几率被抢走一个最小价值的食物,否则可以等概率获得所有食物中价值小于你拥有的食物中最大价值中的一个,问总价 ...

  3. [BZOJ1814]Formula 1

    Description: 一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数 Hint: \(n,m<=12\) Solution: 插头dp模板题,注意要讨论多种 ...

  4. [P1005][NOIP2007] 矩阵取数游戏 (DP+高精)

    我不会高精…… 也不会DP…… 这道题即考高精又考DP…… 我要死了 给一个不是高精的代码(当然不能满分) #include<cstdio> #include<iostream> ...

  5. C++学习笔记55:流类库与输入输出

    I/O流的概念及流类库的结构 程序与外界环境的信息交换 当程序与外界环境进行信息交换时,存在着两个对象:程序中的对象,文件对象. 流是一种抽象,负责在数据的生产者和数据的消费者之间建立联系,并管理数据 ...

  6. sqlmap简单使用

    就以实验吧上那个简单的sql注入题为例吧,不过那道题确实经典,把sqlmap的整个使用过程都展现了一遍,先奉上那道题的地址:http://ctf5.shiyanbar.com/web/index_3. ...

  7. [转]开源.net 混淆器ConfuserEx介绍

    今天给大家介绍一个开源.net混淆器——ConfuserEx http://yck1509.github.io/ConfuserEx/ 由于项目中要用到.net 混淆器,网上搜寻了很多款,比如Dotf ...

  8. nginx配置实例

    user root root; worker_processes ; #error_log logs/error.log; #error_log logs/error.log notice; #err ...

  9. 修改Electron的libcc(libchromiumcontent)源码,重新编译electron, 设置event.isTrusted为true

    VPN非常注意: 编译的过程需要使用VPN, 否者chromium的源代码无法下载, 后面会出现总总问题 Electron的编译环境, 推荐使用物理机: win10 64位 英文版, 为了避免后期出现 ...

  10. Java WebSocket实现网络聊天室(群聊+私聊)

    1.简单说明 在网上看到一份比较nice的基于webSocket网页聊天项目,准备看看学习学习,如是有了这篇文章!原博主博客:http://blog.csdn.net/Amayadream/artic ...