http://wangzhezhe.github.io/blog/2016/01/22/golangmapaddressability-dot-md/

在golang中关于map可达性的问题(addresable?)

在go playground中有这样的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import (
"fmt"
) type Type struct {
A string
} func main() {
items := make(map[string]Type)
items["q"] = Type{}
items["q"].A = "abc"
fmt.Println(items)
}

这样在执行的时候会报一个常见的错误:cannot assign to items["q"].A

改变一下value的声明方式,之后再进行类似的操作就可以了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import (
"fmt"
) type Type struct {
A string
} func main() {
items := make(map[string]*Type)
items["q"] = &Type{}
items["q"].A = "abc"
fmt.Printf("%+v", items)
}

在golang设计的时候,map中的value值应该是地址不可达的,就是说直接取map中的元素的地址会报错,比如把上面例子中的main函数改成下边这样:

1
2
3
4
itemsb := make(map[string]Type)
itemsb["p"] = Type{3}
pointer := &itemsb["p"]
fmt.Println(pointer)

会报出cannot take the address of itemsb["p"]的错误。原因大致是因为,在golang中,一个容量不断增长的map可能会导致原来map中的一些元素发生rehashing,使得他们被重新分配到新的storage location上,这样可能会导致原先得到的address变得不可用。就是所谓的map member 的 not addresable。

正如这个答案中写的,map的indexing操作本来就是地址不可达的,这和golang中map的具体实现机制有关,golang中的map并没有保证它们的value值的地址是不可变的,因为value值的地址很有可能被重新分配,就像前面所说的那样。一个修改的办法就是把value值设置成为指针的形式,这样就相当于添加了一个额外的entry,即使真正需要的那个值的位置发生了变化,也可以redirection过去。以后使用map声明一个结构体的value值的时候,这一点要特别注意下。

对于slice的index操作就是地址可达的,对于map则是不可达的,总是使用map的时候要特别注意下。

??map is a reference to the map contents, but it does not hold references (unless it explicitly stores pointers).

相关参考:

https://golang.org/ref/spec#Address_operators

https://code.google.com/p/go/issues/detail?id=3117

https://groups.google.com/forum/#!topic/golang-nuts/4_pabWnsMp0

https://golang.org/ref/spec

http://stackoverflow.com/questions/13101298/calling-a-pointer-method-on-a-struct-in-a-map https://golang.org/ref/spec#Address_operators

http://stackoverflow.com/questions/16059038/can-not-assign-to-a-struct-member-from-map

首先要明确一下,在声明的时候&Type{}与Type{}的区别在哪里

currently map member并非是addressable的。

Golang Map Addressability的更多相关文章

  1. 【GoLang】GoLang map 非线程安全 & 并发度写优化

    Catena (时序存储引擎)中有一个函数的实现备受争议,它从 map 中根据指定的 name 获取一个 metricSource.每一次插入操作都会至少调用一次这个函数,现实场景中该函数调用更是频繁 ...

  2. golang map输出排序

    由于GoLang Map 内部存储是无序的,当需要按顺序获得map存储的key -value值时,应该对遍历出来的结果进行重新排序: 在go 1.8版本后,提供的slice sort 功能使排序更简单 ...

  3. Golang Map实现(一)

    本文学习 Golang 的 Map 数据结构,以及map buckets 的数据组织结构. hash 表是什么 从大学的课本里面,我们学到:hash 表其实就是将key 通过hash算法映射到数组的某 ...

  4. Golang Map实现(四) map 的赋值和扩容

    title: Golang Map 实现 (四) date: 2020-04-28 18:20:30 tags: golang map 操作,是map 实现中较复杂的逻辑.因为当赋值时,为了减少has ...

  5. golang map getkeys

    golang 获取map的keys package main import "fmt" import "reflect" func main() { abc : ...

  6. golang map

    Our friend Monk has been made teacher for the day today by his school professors . He is going to te ...

  7. golang map 读写锁与深度拷贝的坑

    0X01 golang中,map(字典)无法并发读写 简单来说,新建万条线程对同一个map又读又写,会报错. 为此,最好加锁,其实性能影响并不明显. type taskCache struct{ sy ...

  8. Golang map 如何进行删除操作?

    Cyeam 关注 2017.11.02 10:02* 字数 372 阅读 2784评论 0喜欢 3 map 的删除操作 Golang 内置了哈希表,总体上是使用哈希链表实现的,如果出现哈希冲突,就把冲 ...

  9. Golang map并发 读写锁

    golang并发 一:只有写操作 var ( count int l = sync.Mutex{} m = make(map[int]int) ) //全局变量并发写 导致计数错误 func vari ...

随机推荐

  1. day03_13 多分支if语句及作业

    猜年龄升级版 age_of_princal = 56 guess_age = int( input("请输入您猜测的年龄") ) if guess_age == age_of_pr ...

  2. python基础补漏-09-反射

    isinstance class A: passclass B(A): pass b = B()print isinatance(b,A)issubclass 判断某一个类是不是另外一个类的派生类 # ...

  3. python学习-- 理解'*','*args','**','**kwargs'

    刚开始学习Python的时候,对有关args,kwargs,和*的使用感到很困惑.相信对此感到疑惑的人也有很多.我打算通过这个帖子来排解这个疑惑(希望能减少疑惑). 让我们通过以下5步来理解: 1.  ...

  4. Spring 依赖注入(一、注入方式)

    首先装配一个实体类People package com.maya.model; public class People { private int id; private String name; p ...

  5. iOS--------手势识别的详细使用:拖动、缩放、旋转、点击、手势依赖、自定义手势

    1.UIGestureRecognizer介绍 手势识别在iOS上非常重要,手势操作移动设备的重要特征,极大的增加了移动设备使用便捷性. iOS系统在3.2以后,为方便开发这使用一些常用的手势,提供了 ...

  6. UVa——540Team Queue(STL练习map、queue数组的综合使用)

    Team Queue Time Limit:                                                        3000MS                 ...

  7. [LOJ#2255][BZOJ5017][Snoi2017]炸弹

    [LOJ#2255][BZOJ5017][Snoi2017]炸弹 试题描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: ...

  8. bzoj3997[TJOI2015]组合数学(求最长反链的dp)

    组合数学 给出一个网格图,其中某些格子有财宝,每次从左上角出发,只能向下或右走.问至少走多少次才能将财宝捡完.此对此问题变形,假设每个格子中有好多财宝,而每一次经过一个格子至多只能捡走一块财宝,至少走 ...

  9. 【NOIP2016练习】T1 string (计数)

    题意: 思路: ; ..]of int64; n,k,i:longint; ans,x,y:int64; s,t:ansistring; function c(x,y:longint):int64; ...

  10. transform与position:fixed的那些恩怨--摘抄

    1. 前言 在写这篇文章之前,我理解的fixed元素是这样的:(摘自CSS布局基础) 固定定位与absolute定位类型类似,但它的相对移动的坐标是视图(屏幕内的网页窗口)本身.由于视图本身是固定的, ...