Go无法在map中分配给struct字段

lns*_*shi 24 go

我有这样的数据结构:

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),仍然没有运气

有人请帮助我,谢谢.

Jai*_*ano 102

对于那些寻找更简单示例的人:

这是错误的:

type myStruct struct{
   Field int
}

func main() {
   myMap := map[string]myStruct{
        "key":{
            Field: 1,
        },
   }

   myMap["key"].Field = 5
}
Run Code Online (Sandbox Code Playgroud)

因为myMap["key"]它不是“可寻址的”。

这是对的:

type myStruct struct{
   Field int
}

func main(){
   myMap := map[string]myStruct{
       "key":{
           Field: 1,
       },
   }

   // First we get a "copy" of the entry
   if entry, ok := myMap["key"]; ok {

       // Then we modify the copy
       entry.Field = 5
    
       // Then we reassign map entry
       myMap["key"] = entry
   }

   // Now "key".Field is 5
   fmt.Println(myMap) // Prints map[key:{5}]
}
Run Code Online (Sandbox Code Playgroud)

这里有一个工作示例。

  • 对于其他想要更多了解这一点的人来说,[此](https://utcc.utoronto.ca/~cks/space/blog/programming/GoAddressableValues)似乎是对可寻址性的讨论 - 尽管它似乎主要集中在指针,并且没有解释为什么在 Go 语言中做出这个选择(即为什么该语言不编译源代码“分配给数组中的结构体字段”来“创建一个数组结构的临时变量,然后分配给它的一个字段”)。如果有经验的 Gopher 可以解释一下这个选择的合理性,我很乐意理解! (14认同)

Ank*_*mar 19

对于我的用例,我需要经常更新条目。因此,修改副本并将其重新分配给映射条目的效率非常低。另一种方法是使用指向结构的指针。(我知道它并不适合所有用例,但以防万一您的用例足够灵活,可以使用结构体或指向它的指针......)

type bigStruct struct {
    val1 int
    val2 bool
    val3 string
}

newMap := make(map[string]*bigStruct)

newMap["struct1"] = &bigStruct{1, true, "example1"}

// and can now modify the entries normally
newMap["struct1"].val1 = 2
newMap["struct1"].val2 = false
newMap["struct1"].val3 = "example2"
Run Code Online (Sandbox Code Playgroud)

请参阅此处的完整代码。


lns*_*shi 5

首先,对于这个问题,本文中的解决方案为什么在将值设置为结构中的值作为映射中的值时出现“无法分配”错误?工作完美。

然后,最后弄清楚了为什么在我已经更改为使用指针之后,我的情况仍然无法使用,请参考以下非常简单的代码:

a := make([]int, 3)
fmt.Println(len(a))

b := make(map[string] string, 3)
fmt.Println(len(b))
Run Code Online (Sandbox Code Playgroud)

认为输出将是什么?我只是以为一切都会是:3,但实际上对于地图而言,输出将是0

然后稍后在地图初始化过程中,我使用了for循环并使用了此值len(snapshots),这意味着初始化过程将永远不会运行。

是的,这就是原因。

  • 映射的第二个“ make”参数是容量,而不是长度,并且很少使用。 (2认同)