假设如下
type User struct {
name string
}
users := make(map[int]User)
users[5] = User{"Steve"}
Run Code Online (Sandbox Code Playgroud)
为什么不能访问现在存储在地图中的struct实例?
users[5].name = "Mark"
Run Code Online (Sandbox Code Playgroud)
任何人都可以了解如何访问地图存储的结构,或者为什么它不可能的逻辑?
我知道你可以通过制作结构的副本,更改副本和复制回地图来实现这一目标 - 但这是一个代价高昂的复制操作.
我也知道这可以通过在我的地图中存储struct指针来完成,但我也不想这样做.
我有这样的数据结构:
type Snapshot struct {
Key string
Users []Users
}
snapshots := make(map[string] Snapshot, 1)
// then did the initialization
snapshots["test"] = Snapshot {
Key: "testVal",
Users: make([]Users, 0),
}
Run Code Online (Sandbox Code Playgroud)
Users 是另一个结构
然后,当我尝试Users在Users切片中追加一些新值时,如下所示:
snapshots["test"].Users = append(snapshots["test"].Users, user)
Run Code Online (Sandbox Code Playgroud)
我一直收到这个错误:
cannot assign to struct field snapshots["test"].Users in map
Run Code Online (Sandbox Code Playgroud)
也试过这里的解决方法https://github.com/golang/go/issues/3117所以这样:
tmp := snapshots["test"].Users
tmp = append(tmp, user)
snapshots["test"].Users = tmp
Run Code Online (Sandbox Code Playgroud)
但没有运气,仍然完全相同的错误.
并且还试图用指针声明地图,所以:snapshots := make(map[string] *Snapshot, 1),仍然没有运气
有人请帮助我,谢谢.
Go不允许获取地图成员的地址:
// if I do this:
p := &mm["abc"]
// Syntax Error - cannot take the address of mm["abc"]
Run Code Online (Sandbox Code Playgroud)
理由是,如果Go允许获取此地址,则当地图反向存储增长或闪烁时,地址可能变得无效,使用户感到困惑.
但是当Go切片的容量超过它时,Go切片会被重新定位,但Go允许我们获取切片元素的地址:
a := make([]Test, 5)
a[0] = Test{1, "dsfds"}
a[1] = Test{2, "sdfd"}
a[2] = Test{3, "dsf"}
addr1 := reflect.ValueOf(&a[2]).Pointer()
fmt.Println("Address of a[2]: ", addr1)
a = append(a, Test{4, "ssdf"})
addrx := reflect.ValueOf(&a[2]).Pointer()
fmt.Println("Address of a[2] After Append:", addrx)
// Note after append, the first address is invalid
Address of a[2]: 833358258224
Address of a[2] After Append: 833358266416
Run Code Online (Sandbox Code Playgroud)
为什么Go设计得像这样?获取切片元素的地址有什么特别之处?
为什么我们必须首先读取结构,修改它,然后将其写回地图?在修改其他数据结构(如地图或切片)中的结构字段时,我是否缺少某种隐含的隐藏成本?
编辑:我意识到我可以使用指针,但为什么 Go不允许这样做?
type dummy struct {
a int
}
x := make(map[int]dummy)
x[1] = dummy{a:1}
x[1].a = 2
Run Code Online (Sandbox Code Playgroud) 这与为什么禁止获取(&)地图成员的地址,但允许(&)切片元素相同?但我对接受的答案不满意:"切片由支持数组支持,地图不支持."
注意:我现在已经在上面引用的问题中添加了我自己的答案.
问题访问结构的地图(不复制),甚至更好,但其接受的答案说,你不能修改结构值的字段中的地图,因为你不能把它的地址(这是我的问题).
映射由内存结构(可能包括数组)支持,就像切片一样.
那么为什么我不能获取地图值的地址的真正原因是什么?
我想修改一个map struct值.可以使用++或+ =等运算符来修改映射中的数值
func icandothis() {
cmap := make(map[int]complex64)
cmap[1] += complex(1, 0)
fmt.Println(cmap[1])
}
Run Code Online (Sandbox Code Playgroud)
但是结构值不能修改:
type Complex struct {
R float32
I float32
}
func (x *Complex) Add(c Complex) {
x.R += c.R
x.I += c.I
}
func but_i_cannot_do_this() {
cmap := make(map[int]Complex)
//cmap[1].Add(Complex{1, 0})
fmt.Println(cmap[1])
}
func so_i_have_to_do_this() {
cmap := make(map[int]Complex)
c := cmap[1]
c.Add(Complex{1, 0})
cmap[1] = c
fmt.Println(cmap[1])
}
Run Code Online (Sandbox Code Playgroud)