Go 快速入门指南 - make 和 new

概述

new() 函数为数据类型 T 分配一块内存,初始化为类型 T 的零值,返回类型为指向数据的指针,可以用于所有数据类型。

make() 函数除了为数据类型 T 分配内存外,还可以指定长度和容量,返回类型为数据的初始化结构,只限于 切片, Map, 通道

make

什么时候用

声明并初始化 切片, Map, 通道(后面会讲到)。

为什么定义

为什么专门针对切片, Map 和 通道类型定义一个 make 函数呢?
因为这 3 种数据类型要求使用时必须完成初始化,未初始化就使用可能会引发错误,具体规则如下:

  • 未初始化的切片值为 nil, 如果直接获取或设置元素数据会报错
  • 未初始化的 Map 值为 nil, 如果直接设置元素数据会报错
  • 未初始化的 通道 值为 nil, 发送数据和接收数据会阻塞 (详情在后面通道章节介绍)

未初始化的切片

package main

func main() {
    var s []int

    // 直接获取值: 报错
    _ = s[0]

    // 直接设置值: 同样报错
    //s[0] = 100
}

// $ go run main.go
// 输出如下 
/**
panic: runtime error: index out of range [0] with length 0
...
exit status 2
*/

未初始化的 Map

package main

func main() {
    var m map[int]string

    // 直接设置值: 报错
    m[100] = "hello world"
}

// $ go run main.go
// 输出如下 
/**
panic: panic: assignment to entry in nil map
...
exit status 2
*/

append()

为什么切片即使是 nil, 却可以调用 append() 函数呢? 因为 append() 函数内部实现中做了兼容,如果切片为 nil
那么会先申请好需要的内存空间,然后在复制给切片,等于 覆盖掉原来的切片,这样就不会报错了。

使用 new 初始化切片和 Map

如果我们不使用 make() 函数创建切片和 Map 可以吗? 当然是可以的, new()
函数可以创建任何数据类型,当然也包括切片和 Map
但是 new() 函数返回的指针指向的是类型的 零值,对于切片和 Map 来说, 零值依然是 nil, 这又回到了上面的问题。

new() 创建的切片

package main

import "fmt"

func main() {
    s := new([]int)

    fmt.Printf("s type = %T, val = %#v\n", *s, *s)

    // 直接获取值: 报错
    _ = (*s)[0]

    // 直接设置值: 同样报错
    //s[0] = 100
}

// $ go run main.go
// 输出如下 
/**
s type = []int, val = []int(nil)
panic: runtime error: index out of range [0] with length 0
...
exit status 2
*/

new() 创建的 Map

package main

import "fmt"

func main() {
    m := new(map[int]string)

    fmt.Printf("s type = %T, val = %#v\n", *m, *m)

    // 直接设置值: 报错
    (*m)[100] = "hello world"
}

// $ go run main.go
// 输出如下 
/**
m type = map[int]string, val = map[int]string(nil)
panic: assignment to entry in nil map
...
exit status 2
*/

new

什么时候用

除了 切片, Map, 通道(后面会讲到) 以外的其他数据类型。

小结

初始化 切片, Map, 通道 三种数据类型时,使用 make() 函数,初始化其他数据类型时,使用 new() 函数。

联系我

0 条评论
请不要发布违法违规有害信息,如发现请及时举报或反馈
还没有人评论呢,速度抢占沙发!
相关文章
  • 人工智能神经网络( Artificial Neural Network,又称为ANN)是一种由人工神经元组成的网络结构,神经网络结构是所有机器学习的基本结构,换句话说,无论是深度学习还是强化学习都是基...

  • 一、算术运算符 运算符描述 + 相加 - 相减 * 相乘 / 相除 % 求余 代码示例: package main import "fmt" fun...

  • 背景 golang可以获取命令执行的输出结果,但要执行完才能够获取。 如果执行的命令是ssh,我们要实时获取,并执行相应的操作呢? 示例 func main() { user := "root"...

  • 概述建议先阅读 range, 非缓冲通道, 缓冲通道。range 除了可以遍历字符串、切片、数组等数据结构外,还可以遍历通道。语法规则和遍历其他数据结构不同,遍历通道时没有 索引 的概念,只有值,语法...

  • 普通打印优点:内置函数,不需要引入额外的包,简单方便。不足:无法进行格式化打印,无法完整打印复合数据结构 (如数组, Map 等)。println 函数打印多个传入的参数,并自动加一个换行。例子pac...

  • 项目中的dao层,我们用来查询数据库,获取想要数据。有时我们会需要查询数据给结构体赋值,并返回一个结构体指针,如下 // 结构体字段已与数据库对应 func GetCommunity(id int) ...

  • crony - 分布式定时任务管理平台 1. 基本介绍 1.1 项目背景 项目中存在许多定时任务,很多代码写法都是采取见缝插针式的写法或者直接丢到task服务里面写,存在以下问题 服...

  • 切片 Go语言切片是一种建立在数组类型之上的抽象,它构建在数组之上并且提供更强大的能力和便捷。解决了数组长度不可变等缺陷 声明切片 切片的数据结构非常小,只有三个字段:指向底层数组的指针,切片...

  • 在Golang中,我们可以使用标准库中的encoding/json包来将JSON数据转换为结构体。本文将介绍如何使用该包将JSON数据转换为Golang结构体。 首先,让我们看一下JSON数据的格式。...

  • 一 kibana介绍 Kibana :是一个开源的分析和可视化平台,旨在与 Elasticsearch 合作。Kibana 提供搜索、查看和与存储在 Elasticsearch 索引中的数据进行交互...

  • 我现在的数据在sqlite中,保存在mac本地的一个文件中。用了electron+vue搭建了一个客户端。 我大概希望是这样的逻辑,先加载本地db文件,然后再获取数据。 这里就有一个问题,我怎么获取...

  • 概述使用的场景:在函数内部有很多重复性代码并且严重依赖上下文变量。此时可以在函数内部声明一个函数,专门用来处理重复性的代码。例子内部求和函数package main import "fmt" fu...

  • dongle 是一个轻量级、语义化、对开发者友好的 Golang 编码解码和加密解密库Dongle 已被 awesome-go 收录, 如果您觉得不错,请给个 star 吧github.com/gol...

  • 获取微信昵称、头像、OpenID 微信公众号服务号的网页授权功能开发,主要是通过js跳转到一个微信提供的url 然后微信会弹出获取昵称头像的按钮 允许获取后,会回跳到我们的网址上,并且带着一个code...

  • 前言 之前一篇文章介绍了 日志库zap https://www.cnblogs.com/zichliang/p/17311480.html 毋庸置疑,zap库无论是Golang在项目中 还是生产中都极...

  • 正文: 现在需要你写一个程序,从 3 开始依次向下,当到 0 时打印 「GO!」 并退出,要求每次打印从新的一行开始且打印间隔一秒的停顿。 3   2   1   Go!   我们将通过...

  • 面向对象介绍 面向对象和面向过程都是解决问题的一种思路。 面向过程: 是一种以过程为中心的编程思想,实现功能的每一步都是自己实现的。面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能...

  • 在gRPC里,客户端可以像调用本地方法一样直接调用其他机器上的服务端应用程序的方法,帮助你更容易创建分布式应用程序和服务。与许多RPC系统一样,gRPC是基于定义一个服务,指定一个可以远程调用的带有参...

  • 一 Zap日志介绍 Zap是在 Go 中实现超快、结构化、分级的日志记录。 Zap日志能够提供下面这些功能:   1、能够将事件记录到文件中,也可以在应用控制台输出   2、日志切割-可以...

  • 概述Go 箴言: 不要通过共享内存来通信,而要通过通信来共享内存。阻塞通道与非阻塞通道通过关键字 chan + 数据类型 来表明通道数据类型,调用 make() 函数来初始化一个通道。make() 函...