Go 中的映射初始化

2024-01-01

据我了解,类型slice and map在很多方面与 Go 相似。他们两个reference (or container) 类型。就抽象数据类型而言,它们分别表示数组和关联数组。

然而,他们的行为却截然不同。

var s []int
var m map[int]int

虽然我们可以立即使用声明的切片(附加新项目或重新切片),但我们无法对新声明的映射执行任何操作。我们必须打电话make函数并显式初始化映射。因此,如果某个结构体包含映射,我们必须为该结构体编写一个构造函数。

所以,问题是为什么不能添加一些语法糖并在声明映射时分配和初始化内存。

我确实用谷歌搜索了这个问题,学到了一个新词“autovivification”,但仍然看不到原因。

我不是在谈论结构文字。是的,您可以通过提供诸如m := map[int]int{1: 1}。然而,如果你有一些struct https://play.golang.org/p/A1GgAndnccD:

package main

import (
    "fmt"
)

type SomeStruct struct {
    someField map[int]int
    someField2 []int
}

func main() {
    s := SomeStruct{}
    s.someField2 = append(s.someField2, -1) // OK
    s.someField[0] = -1 // panic: assignment to entry in nil map
    fmt.Println(s)
}

不可能立即使用结构(所有字段都使用默认值)。必须创建一个构造函数SomeStruct它必须显式初始化地图。


虽然我们可以立即使用声明的切片(附加新项目或重新切片),但我们无法对新声明的映射执行任何操作。我们必须打电话make函数并显式初始化映射。因此,如果某个结构体包含映射,我们必须为该结构体编写一个构造函数。

这不是真的。默认值——或更准确地说零值 https://golang.org/ref/spec#The_zero_value–对于切片和贴图来说都是nil。你可以做“同样的”nil地图,就像你可以用nil片。您可以检查 a 的长度nil地图,您可以索引nil映射(结果将是映射值类型的零值),例如以下全部有效:

var m map[int]int

fmt.Println(m == nil) // Prints true
fmt.Println(len(m))   // Prints 0
fmt.Println(m[2])     // Prints 0

尝试一下去游乐场 https://play.golang.org/p/ff7UiRB3kq1.

您对零值切片的更多“感觉”是您可以向其添加值。这是事实,但在幕后,将使用确切的分配新切片make() https://golang.org/pkg/builtin/#make您必须为映射调用内置函数才能向其中添加条目,并且必须(重新)分配返回的切片。因此,零值切片比零值映射“不再可供使用”。append() https://golang.org/pkg/builtin/#append只是负责必要的(重新)分配和复制。我们可以有一个“等价物”addEntry()您可以向其传递映射值和键值对的函数,并且如果传递的映射是nil,它可以分配一个新的映射值并返回它。如果你不打电话append(),您不能向 a 添加值nil切片,就像您不能向切片添加条目一样nil map.

切片和映射为零值的主要原因是nil(而不是初始化的切片或映射)是性能和效率。通常,映射或切片值(变量或结构字段)永远不会被使用,或者不会立即使用,因此如果在声明时分配它们,那将浪费内存(和一些 CPU)资源,更不用说它给垃圾收集器带来了更多的工作。此外,如果零值是一个初始化值,它通常是不够的(例如,0 大小的切片不能容纳任何元素),并且当您向其中添加新元素时,它通常会被丢弃(因此初始分配将是完全浪费)。

是的,在某些情况下您确实想立即使用切片和映射,在这种情况下您可以调用make()您自己,或使用复合文字 https://golang.org/ref/spec#Composite_literals。您还可以使用特殊形式make()您可以在其中提供地图的(初始)容量,避免未来对地图内部结构进行重组(这通常需要不可忽略的计算)。自动非nil默认值无法猜测您需要什么容量。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Go 中的映射初始化 的相关文章

  • 完全删除使用“go get”安装的软件包?

    我正在使用 Go 1 13 1 最新版本 我正在尝试完全删除我安装的软件包go get来自 GitHub 这go clean i
  • 在 Go 中使用电子邮件地址创建证书签名请求 (CSR)

    我尝试使用 crypto x509 包生成 CSR 但没有找到将 emailAddress 字段添加到其主题中的方法 根据文档证书申请 http golang org pkg crypto x509 CertificateRequest结构
  • C++ 11 相当于 java.util.ConcurrentHashMap

    我发现自己不断地编写互斥体代码 以便同步对 std unordered map 和其他容器的读 写访问 以便我可以像使用 java util concurrent 容器一样使用它们 我正要开始编写一个包装器来封装互斥体 但我宁愿使用经过良好
  • 如何从非英语字符串解析go中的月份

    我想将以下字符串解析为 go 中的日期 This item will be released on March 9 2014 我跟着this https stackoverflow com questions 14106541 go par
  • 如何解决内存碎片

    我们偶尔会遇到这样的问题 长时间运行的服务器进程 在 Windows Server 2003 上运行 由于内存分配失败而引发异常 我们怀疑这些分配由于内存碎片而失败 因此 我们一直在寻找一些可能对我们有帮助的替代内存分配机制 我希望有人能告
  • 空检查时可能未初始化错误

    我正在检查变量是否已初始化 但此时 netbeans 给了我variable reader might not have been initialized警告 我该如何解决 抑制这个问题 这是我的代码 摘要 final Reader rea
  • 使用 OpenTelemetry 统一不同服务的范围

    我刚刚开始使用 OpenTelemetry 并为此创建了两个 微 服务 Standard and GeoMap 最终用户将请求发送到Standard服务 该服务又将请求发送到GeoMap在将结果返回给最终用户之前获取信息 我使用 gRPC
  • 调整巨大数组的大小

    我正在我的应用程序中处理巨大的数组 需要调整它们的大小 假设您有一个 2Gb 的阵列 并且想要将其大小调整为 3Gb 有没有办法在暂时不需要 5Gb 的情况下调整它的大小 例如 给定一个 1Gb 堆 使用 Xmx1G flag public
  • 使用 .fromkeys 初始化嵌套字典[重复]

    这个问题在这里已经有答案了 您好 我想知道创建嵌套字典时使用 fromkeys 方法创建嵌套字典不起作用 x 1 2 3 4 5 y 7 8 9 10 11 zx dict fromkeys x dict fromkeys y 0 它创建一
  • gcc 没有小字符串优化吗?

    Most std string实现 包括 GCC 使用小字符串优化 例如 有一个answer https stackoverflow com a 21710033 2640636讨论这个 今天 我决定检查我编译的代码中的字符串在什么时候被移
  • 如何在 Spring 中将多个映射合并为一个

    我的上下文文件中定义了几个地图 有没有一种方法可以将这些映射组合成一个包含其所有条目的映射 而无需编写 Java 代码 并且无需使用嵌套映射 我正在寻找 Map m new HashMap 的等效项m putAll carMap m put
  • 使用覆盖率信息测试 Go 中的 os.Exit 场景 (coveralls.io/Goveralls)

    这个问题 如何在 Go 中测试 os exit 场景 https stackoverflow com questions 26225513 how to test os exit scenarios in go 以及其中得票最高的答案 列出
  • 如何检测在 MapView 中选择了哪个注释

    我在地图内做了一些注释 当我点击它们时 我会看到一些信息 并且有一个打开地图的按钮 并且使用我无法接受的正确信息应该可以绘制出我的路线 这是我的代码 我有 2 个双精度数组用于我的经纬度 我从查询中填充了它们 var lat Double
  • 如何在 Go 中从 stdin 解析无限 json 数组?

    我正在尝试编写一个 i3status 的小替代品 一个与 i3bar 兼容的小程序进行通信this http i3wm org docs i3bar protocol html协议 他们通过标准输入和标准输出交换消息 两个方向的流都是一个无
  • 在 Go/ 中创建/更新 google 驱动器权限/ [使用 api 创建电子表格但无法访问它]

    我正在尝试使用 google Drive api 和以下代码创建电子表格 但我无法访问它 update 该文件似乎不在我在这里指定的驱动器中 有人知道为什么会发生这种情况吗 update 在字段中添加了父母 但有 404 错误 说找不到文件
  • Python 中字典的合并层次结构

    我有两本词典 而我想做的事情有点奇怪 基本上 我想合并它们 这很简单 但它们是字典的层次结构 我想以这样的方式合并它们 如果字典中的项目本身就是字典并且存在于两者中 我也想合并这些字典 如果它不是字典 我希望第二个字典中的值覆盖第一个字典中
  • 尝试了解 ARM 二进制映像中的加载内存地址 (LMA) 和二进制文件偏移量

    我在一家ARM 皮质 M4 STM32F4xxxx 我试图了解二进制文件 elf and bin 在内存中构建并闪存 特别是关于内存位置 具体来说 我不明白的是LMA从实际的二进制文件偏移量进行 翻译 让我用一个例子来解释一下 我有一个 e
  • 使用 MAX_ORDER / 包含 mmzone.h

    根据https www kernel org doc Documentation networking packet mmap txt https www kernel org doc Documentation networking pa
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • 是否可以使用 go:generate 重定向 stdin/stdout

    我有一个充当管道的工具 它从标准输入读取数据并将源代码写入标准输出 是否可以设置输入 输出重定向并将此类工具与 go generate 一起使用 就像是 go generate tool lt file txt gt file go 我想出

随机推荐