为什么切片值有时会过时但永远不会映射值?

2024-01-11

我发现切片映射函数和通道经常被一起提到参考类型。但是我注意到切片某些东西没有表现出任何参考行为,就像它们可能会变得陈旧一样:

   var s []int
   //must update slice value
   s = append(s, ...) 

or

   //must use pointer if we want to expose the change
   func foo(s *[]int) error  
   //or change the function signature to return it like _append_
   func foo(s []int) (r slice, err error)

通常我通过牢记切片描述符实现的内部组件来理解这一点:切片值可以看作是 len、cap 和数据指针的结构。

但地图值永远不需要像

   m := make(map[string]int)
   ...
   // don't know how to express with insertion, but you know what i mean.
   m = delete(m, "well")  

为什么?映射值只是指向映射描述符的指针吗?如果是这样为什么不也这样制作切片呢?


在 Go 中,没有像 C++ 中那样的引用类型。在 Go 中,一切都是按值传递的。当 Go 中使用术语“引用类型”时,它意味着引用它们应该表示的数据的类型(通过指针)。

切片是由类型表示的小型、类似结构的数据结构reflect.SliceHeader https://golang.org/pkg/reflect/#SliceHeader:

type SliceHeader struct {
        Data uintptr
        Len  int
        Cap  int
}

它包含一个指向基础数组中切片的第一个元素的指针(SliceHeader.Data场地)。该结构体很小,并且可以有效地作为值传递,无需传递其地址(并取消引用它以间接访问其任何字段)。切片的元素不存储在切片头中,而是存储在头内存区域之外的数组中。这意味着修改“指向”元素将修改原始切片的元素。

当您向切片追加(超过 0 个)元素时,Len标头中的字段必须更改,因此描述具有附加元素的切片的新切片必须与追加之前的切片不同,这就是为什么您需要分配内置函数的返回值append()功能。 (其他值也可能会改变,但是Len肯定必须改变。)

映射被实现为指向runtime.hmap结构:

type hmap struct {
    // Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.
    // Make sure this stays in sync with the compiler's definition.
    count     int // # live cells == size of map.  Must be first (used by len() builtin)
    flags     uint8
    B         uint8  // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
    noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
    hash0     uint32 // hash seed

    buckets    unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
    oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
    nevacuate  uintptr        // progress counter for evacuation (buckets less than this have been evacuated)

    extra *mapextra // optional fields
}

正如您所看到的,这是一个比切片头复杂得多的数据结构,并且要大得多,将其作为值传递并不高效。

从映射中添加/删除元素(键值对)存储在该结构体的字段引用的存储桶中,但由于映射在底层被作为指针处理,因此您不需要分配此类操作的结果。

为了完整起见,通道也被实现为指针,指向runtime包的hchan type:

type hchan struct {
    qcount   uint           // total data in the queue
    dataqsiz uint           // size of the circular queue
    buf      unsafe.Pointer // points to an array of dataqsiz elements
    elemsize uint16
    closed   uint32
    elemtype *_type // element type
    sendx    uint   // send index
    recvx    uint   // receive index
    recvq    waitq  // list of recv waiters
    sendq    waitq  // list of send waiters

    // lock protects all fields in hchan, as well as several
    // fields in sudogs blocked on this channel.
    //
    // Do not change another G's status while holding this lock
    // (in particular, do not ready a G), as this can deadlock
    // with stack shrinking.
    lock mutex
}

这又是一个“胖”结构,并且像映射值一样处理。

查看相关问题:

参数中使用的切片与映射 https://stackoverflow.com/questions/47590444/slice-vs-map-to-be-used-in-parameter/47590531#47590531

使用值接收器附加到具有足够容量的切片 https://stackoverflow.com/questions/53009514/appending-to-a-slice-with-enough-capacity-using-value-receiver/53009770#53009770

golang切片是按值传递的吗? https://stackoverflow.com/questions/39993688/are-golang-slices-pass-by-value/39993797#39993797

Go 中的“值语义”和“指针语义”是什么意思? https://stackoverflow.com/questions/51264339/what-do-value-semantics-and-pointer-semantics-mean-in-go/51265000#51265000

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

为什么切片值有时会过时但永远不会映射值? 的相关文章

  • 从字典的元素创建 Pandas 数据框

    我正在尝试从字典创建一个 pandas 数据框 字典设置为 nvalues y1 1 2 3 4 y2 5 6 7 8 y3 a b c d 我希望数据框仅包含 y1 and y2 到目前为止我可以使用 df pd DataFrame fr
  • 如何在 Linux 中编写文本模式 GUI? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 当我编写脚本 程序时 我经常想弹出一个简单的文本 gui 来提示输入 我该怎么做 例如 来自 Shel
  • 嵌套字典中的 Django 模板

    我正在使用 Django 模板 并且遇到了嵌套字典的一个问题 Dict result dict type 0 file name abc count 0 type 1 file name xyz count 50 我的 HTML 文件中的模
  • 在Python中如何获取字典的部分视图?

    是否有可能获得部分视图dict在Python中类似于pandasdf tail df head 说你有很长一段时间dict 而您只想检查某些元素 开头 结尾等 dict 就像是 dict head 3 To see the first 3
  • C 中的指针、数组、字符串和 Malloc

    我目前正在学习 C 语言中的字符串 指针和数组 我尝试编写一个程序 其中数组保存三个指向字符串地址的指针 这一切似乎都有效 但程序的行为很奇怪 这是代码 char getUserDetails char host localhost cha
  • 正确的文件扩展名或缩写是什么。 golang 的文本/模板?

    我正在考虑为其创建语法荧光笔 但我不知道这种特定类型模板的常规缩写 In 例子之一 http golang org pkg text template example Template helpers从文本 模板 godoc 中 它们引用
  • 如何使信号量超时

    Go 中的信号量是通过通道来实现的 一个例子是这样的 https sites google com site gopatterns concurrency semaphores https sites google com site gop
  • python:查找围绕某个 GPS 位置的圆的 GPS 坐标的优雅方法

    我有一组以十进制表示的 GPS 坐标 并且我正在寻找一种方法来查找每个位置周围半径可变的圆中的坐标 这是一个例子 http green and energy com downloads test circle html我需要什么 这是一个圆
  • C++:向 std::sort 提供模板化比较函数

    假设我想让 std sort 根据指针指向的 int 值对指向 int 的指针向量进行排序 忽略那里明显的性能问题 很简单吧 做一个函数 bool sort helper const int a const int b return a l
  • Golang 正则表达式在字符串之间替换

    我有一些可能采用以下形式的字符串 MYSTRING MYSTRING n MYSTRING n MYSTRING randomstringwithvariablelength n 我希望能够将其正则表达式为MYSTRING foo 基本上替
  • C++ 在 std::map 中存储对值的引用

    我是否正确地假设向 std map 添加 删除元素不会影响其他元素 即导致它们在内存中重新定位 因此以下内容是安全的 我查看了各个网站上有关容器的信息 但只发现了迭代器无效的情况 这是我已经知道的 std map
  • 多重映射的每个元素是否都包含键和值?

    我无法想象没有人问过这个问题 但我没有运气找到它 a 的每个元素是否multimap包含它的价值and它的钥匙 这就是a的内部结构multimap看起来更像这样 map
  • iOS:Swift - 如何在触摸时向地图添加精确定位并获取该位置的详细地址?

    我想在 iOS 地图的触摸上添加注释并获取各个位置的详细地址 地标 我如何在 Swift 中实现这一目标 提前致谢 要对地图上的触摸做出反应 您需要为地图视图设置点击识别器 in viewDidLoad let gestureRecogni
  • os.Mkdir 和 os.MkdirAll 权限

    我正在尝试在程序开始时创建一个日志文件 我需要检查是否 log如果不创建目录 则目录存在 然后继续创建日志文件 好吧 我尝试使用os Mkdir 也os MkdirAll 但无论我在第二个参数中输入什么值 我都会得到一个没有权限的锁定文件夹
  • 无法理解 Java 地图条目集

    我正在看一个 java 刽子手游戏 https github com leleah EvilHangman blob master EvilHangman java https github com leleah EvilHangman b
  • JNI 将 Char* 2D 数组传递给 JAVA 代码

    我想从 C 代码通过 JNI 层传递以下指针数组 char result MAXTEST MAXRESPONSE 12 12 8 3 29 70 5 2 42 42 在java代码中我写了以下声明 public static native
  • 使用函数更改指针包含的地址

    如果我声明了一个指针p as int p 在主模块中 我可以更改包含的地址p通过分配p a where a是另一个已经声明的整型变量 我现在想通过使用以下函数来更改地址 void change adrs int q int newad q
  • 将数据帧行转换为字典

    我有像下面的示例数据这样的数据帧 我正在尝试将数据帧中的一行转换为类似于下面所需输出的字典 但是当我使用 to dict 时 我得到了索引和列值 有谁知道如何将行转换为像所需输出那样的字典 任何提示都非常感激 Sample data pri
  • 更改 R 中 ggplot geom_polygon 的颜色方案

    我正在使用地图库和 ggplot 的 geom polygon 创建地图 我只是想将默认的蓝色 红色 紫色配色方案更改为其他颜色 我对 ggplot 非常陌生 所以如果我没有使用正确的数据类型 请原谅 我使用的数据如下所示 gt head
  • select 语句是否保证通道选择的顺序?

    继从这个答案 https stackoverflow com a 25795236 274460 如果一个 goroutine 在两个通道上进行选择 是否保证通道的选择顺序与其发送的顺序相同 我对发送者是单线程的情况特别感兴趣 例如 是否保

随机推荐

  • 运行时未定义枚举类型

    我遇到一个问题 Typescript 编译器成功编译了我的代码 但运行时却给出了未定义的类型错误 在我的应用程序中我创建了一个types ts文件 其中一些内容在多个其他 ts 文件之间共享 它包含一个字符串枚举 例如 enum MyEnu
  • 强制另存为 XLSM,同时维护文件结构

    因此 我正在使用 XLTM 文件 并且我希望用户确保它们保存为 XLSM 当他们单击 保存 时 效果很好 但我发现当他们单击 另存为 时 文件被保存为 xlsm xlsm 我对如何确保用户保存为 XLSM 同时将文件名保留为 filenam
  • 作为 JavaScript 开发人员如何学习 Haxe

    我使用 JS 已经三年了 我想使用 OpenFL 制作移动应用程序 不过 我不知道Haxe 而且我也不知道其他编程语言 不过 学习类 继承等我还是很舒服的 另外 据我所知 OpenFL 在性能方面优于 Adob e AIR 并且您需要了解
  • AngularJS UI Router 在工厂/服务中使用解析的依赖关系

    我有一个 UI Router 定义如下 为简单起见进行了修剪 stateProvider state someState resolve model modelService info function modelService info
  • Python:Pandas Dataframe 如何将 timedelta 列转换为 float 列

    我的数据框中有一列数据类型为 timedelta64 ns 我正在尝试将其转换为浮点数 这是一个示例表 ColA 227 days 00 00 00 000000000 316 days 00 00 00 000000000 226 day
  • 如何将 CSS 滤镜应用到背景图像

    我有一个 JPEG 文件 用作搜索页面的背景图像 并且我使用 CSS 来设置它 因为我正在使用骨干网 js https en wikipedia org wiki Backbone js上下文 background image url wh
  • 如何更改 Hibernate 日志记录级别?

    如何以编程方式更改 Hibernate 日志记录级别 休眠使用SLF4j http slf4j org 因为它是日志 API 查看此 API 我找不到任何以编程方式调整日志记录级别的方法 所以我认为你必须直接使用底层运行时日志系统 这取决于
  • ANTLR2 与 ANTLR3

    您使用过其中一个或两者吗 您更喜欢哪一个 出于什么原因 例如 我最近学习了 v2 并且由于 netbeans 团队提供的高性能实现 是的 我被 java 困住了 我可能会坚持使用它 在这种情况下 是否有任何令人信服的理由进行转换 要了解 v
  • 加密 SQL 连接字符串 C#

    我创建了一个连接到 sql 2005 服务器的 C 应用程序 不是 asp 网页 在我的源代码中 该 sql 服务器的密码和用户 ID 在 ConnectionString 中以纯文本形式编码 SqlConnection con new S
  • 使用 Parallel.ForEach() 线程安全吗?

    本质上 我正在处理这个 var data input AsParallel List
  • Gson用不同的数据解析相同的密钥

    如何解析服务器接收到的包含不同键值的数据 location id 1 id 2 and location id 1 不确定如何处理以下对象 public class UserLocation SerializedName location
  • 要求关联类型可以在 @convention(c) 块中表示

    我想要一种通用的方法来做类似 Swift 3 的事情 public protocol Callable associatedtype In CVarArg associatedtype Out CVarArg public struct I
  • 如何让 Twitter 引导日期选择器与 Meteor 一起使用?

    我宁愿使用 Bootstrap 的 Meteor 包实现 而不是文件较少的版本 但我很难让日期选择器工作 似乎有处于不同状态的三个版本 最后一个版本由 Aymkdn 编译并准备就绪 http www eyecon ro bootstrap
  • 如何将 JSON 数据加载到 A-Frame 组件中?

    将自定义 JSON 文件作为数据加载到 A 框架组件中的最佳方法是什么 例如 JSON 文件可能包含点的坐标 我想将文件作为资产加载并在组件中使用解析后的 json 对象 coordinates x 0 y 1 z 2 You can 在架
  • XSL:有没有一种简单的方法可以防止寡妇?

    我本来希望打电话
  • Android Studio 错误:无法解析 Xml 中的符号

    我正在关注 google Android Studio 第一个 Android 应用程序教程 但是当我尝试向我的应用程序添加搜索栏时 我现在遇到了 3 个奇怪的错误 我现在就在这里 就像教程一样添加了 XML 代码 http develop
  • 在随机坐标数组中使用 CollideRect

    现在 我的游戏正确地将所有图像传输到随机位置 并且也正确获取图像的矩形 但我不知道如何使用 colliderect 来确保图像不重叠 它如何适用于我的代码 另外 我试图让第一个文本淡出 但我不知道为什么它对我不起作用 这是代码 class
  • 在 Angular2 应用程序中运行 ng 服务时出现错误“无法读取未定义的属性‘长度’”

    使用 angular cli 命令 ng serve 运行 angular2 应用程序时 我遇到以下问题 电子邮件受保护 cdn cgi l email protection启动 C Users padmavathi Downloads p
  • 如何向 AVPlayerViewController 添加自定义按钮?

    有没有什么方法可以将 向后 前进跳过 30 分钟 按钮添加到子类 AVPlayerViewController 中 使其看起来像原生的 就像播放 暂停按钮一样 实际上没有 好的 方法可以做到这一点 Apple 保持 AVPlayerView
  • 为什么切片值有时会过时但永远不会映射值?

    我发现切片映射函数和通道经常被一起提到参考类型 但是我注意到切片某些东西没有表现出任何参考行为 就像它们可能会变得陈旧一样 var s int must update slice value s append s or must use p