如何在Go中清除地图?

lav*_*vin 63 go

我正在寻找像.clear() 原始类型的c ++函数map.

或者我应该只创建一个新地图?

更新:感谢您的回答.通过查看答案,我才意识到有时候创建一个新地图可能会导致一些我们不想要的不一致.请考虑以下示例:

var a map[string]string
var b map[string]string

func main() {
    a = make(map[string]string)
    b=a
    a["hello"]="world"
    a = nil
    fmt.Println(b["hello"])
}
Run Code Online (Sandbox Code Playgroud)

我的意思是,这仍然与.clear()c ++中的函数不同,后者将清除对象中的内容.

Lil*_*ard 79

您可能应该只创建一个新地图.没有理由去尝试清除现有的一个,除非多个代码引用相同的映射,并且一个明确需要清除值,以便其他代码片段可以看到此更改.

所以,是的,你应该只是说

mymap = make(map[keytype]valtype)
Run Code Online (Sandbox Code Playgroud)

如果您确实需要清除现有地图,无论出于何种原因,这很简单:

for k := range m {
    delete(m, k)
}
Run Code Online (Sandbox Code Playgroud)

  • 从Go 1.11开始,编译器优化了该表单的映射清除操作.https://github.com/golang/go/blob/master/doc/go1.11.html (13认同)
  • 在迭代所有值的同时修改地图的内容真的可以吗?其他语言将无法正常工作。 (7认同)
  • @JohnJeffery:我在发布之前对此进行了测试.似乎工作.规范中的实际语言说"地图上的迭代顺序没有指定,并且不保证从一次迭代到下一次迭代是相同的.如果在迭代期间删除尚未到达的映射条目,则不会生成相应的迭代值.如果在迭代期间插入了映射条目,则行为依赖于实现,但每个条目的迭代值最多只会生成一次.如果地图为零,则迭代次数为0.这表明它是支持的. (3认同)
  • 更新了上述编译器优化的发行说明链接:https://golang.org/doc/go1.11#performance-compiler (2认同)

bla*_*een 26

去1.21

\n

使用内置的clear.

\n
func main() {\n    m := map[string]int{"foo": 1}\n    clear(m)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这是一个单一的函数调用,并且具有次要但重要的优点,即它将删除非自反键(有关这意味着什么的详细信息,请参阅下文)。标准库maps包已经没有了maps.Clear

\n

从 1.18 到 1.20

\n

您可以使用maps.Clear。该函数属于该包golang.org/x/exp/maps(实验性且不在兼容性保证范围内)

\n
\n

Clear 删除 m 中的所有条目,使其为空。

\n
\n

用法示例:

\n
func main() {\n    testMap := map[string]int{"gopher": 1, "badger": 2}\n    maps.Clear(testMap)\n    fmt.Println(testMap)\n    \n    testMap["zebra"] = 2000\n    fmt.Println(testMap)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

游乐场:https://go.dev/play/p/qIdnGrd0CYs?v =gotip

\n

如果你不想依赖实验包,你可以复制粘贴源代码,这实际上非常简单:

\n
func Clear[M ~map[K]V, K comparable, V any](m M) {\n    for k := range m {\n        delete(m, k)\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

重要提示:就像使用delete\xe2\x80\x94 的实现maps.Clear使用 \xe2\x80\x94 的内置 \xe2\x80\x94 一样,这不会从映射中删除非自反键。原因是对于非自反键,根据定义,x == x是错误的。非反身键是 NaN 浮点数以及支持比较运算符但在某处包含 NaN 浮点数的所有其他类型。

\n

请参阅此代码以了解这意味着什么:

\n
func main() {\n    m := map[float64]string{}\n    m[1.0] = "foo"\n\n    k := math.NaN()\n    fmt.Println(k == k) // false\n    m[k] = "bar"\n\n    maps.Clear(m)\n    fmt.Printf("len: %d, content: %v\\n", len(m), m) \n    // len: 1, content: map[NaN:bar]\n\n    a := map[[2]float64]string{}\n    a[[2]float64{1.0, 2.0}] = "foo"\n\n    h := [2]float64{1.0, math.NaN()}\n    fmt.Println(h == h) // false\n    a[h] = "bar"\n\n    maps.Clear(a)\n    fmt.Printf("len: %d, content: %v\\n", len(a), a) \n    // len: 1, content: map[[1 NaN]:bar]\n}\n
Run Code Online (Sandbox Code Playgroud)\n

游乐场:https://go.dev/play/p/LWfiD3iPA8Q

\n


Joh*_*ith 12

与C++不同,Go是一种垃圾收集语言.你需要以不同的方式思考问题.

当你制作一张新地图时

a := map[string]string{"hello": "world"}
a = make(map[string]string)
Run Code Online (Sandbox Code Playgroud)

原始地图最终将被垃圾收集; 你不需要手动清除它.但请记住,地图(和切片)是参考类型; 你创建它们make().只有在没有对它的引用时,底层映射才会被垃圾收集.因此,当你这样做

a := map[string]string{"hello": "world"}
b := a
a = make(map[string]string)
Run Code Online (Sandbox Code Playgroud)

原始数组不会被垃圾收集(直到b被垃圾收集或b指的是其他东西).

  • `与 C++ 不同,Go 是一种垃圾收集语言。你需要以不同的方式思考问题。`Java、Python、C# 都有 `clear` 并且它们都被垃圾收集了:D (11认同)

Sum*_*mer 6

// Method - I , say book is name of map
for k := range book {
    delete(book, k)
}

// Method - II
book = make(map[string]int)

// Method - III
book = map[string]int{}
Run Code Online (Sandbox Code Playgroud)

  • 方法二和方法三不清除地图。如果某处有一本书的副本,那么行为就会有所不同。例如参见 https://go.dev/play/p/H0VqSTkTC6m (2认同)