【问题标题】:How to clear a map in Go?如何在 Go 中清除地图?
【发布时间】:2022-05-12 17:27:31
【问题描述】:

我正在为原始类型 map 寻找类似 c++ 函数 .clear() 的东西。

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

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

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"])
}

我的意思是,这和c++中的.clear()函数还是有区别的,会清除对象中的内容。

【问题讨论】:

标签: go


【解决方案1】:

您可能应该只创建一个新地图。没有真正的理由费心尝试清除现有的地图,除非多段代码引用了同一个地图,并且其中一段明确需要清除这些值,以便其他代码段可以看到此更改。

所以是的,你可能应该说

mymap = make(map[keytype]valtype)

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

for k := range m {
    delete(m, k)
}

【讨论】:

  • 那么一个一个地删除元素是唯一的办法吗?
  • @lavin:是的。没有内置函数可以执行此操作,并且您不能拥有对任意地图执行此操作的库函数。但无论如何它只有 3 行。
  • 在遍历所有值的同时修改地图的内容真的可以吗?其他语言无法正常使用。
  • @JohnJeffery:我在发布之前对此进行了测试。似乎工作。规范中的实际语言为 The iteration order over maps is not specified and is not guaranteed to be the same from one iteration to the next. If map entries that have not yet been reached are deleted during iteration, the corresponding iteration values will not be produced. If map entries are inserted during iteration, the behavior is implementation-dependent, but the iteration values for each entry will be produced at most once. If the map is nil, the number of iterations is 0. 这表明它受到支持。
  • 更新了上述编译器优化的发行说明链接:golang.org/doc/go1.11#performance-compiler
【解决方案2】:

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

当你制作新地图时

a := map[string]string{"hello": "world"}
a = make(map[string]string)

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

a := map[string]string{"hello": "world"}
b := a
a = make(map[string]string)

原始数组不会被垃圾回收(直到 b 被垃圾回收或 b 引用其他东西)。

【讨论】:

  • Unlike C++, Go is a garbage collected language. You need to think things a bit differently. Java、Python、C# 有clear,它们都被垃圾回收了:D
【解决方案3】:
// 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{}

【讨论】:

    【解决方案4】:

    通用 maps 包 (https://github.com/golang/go/issues/47649) 的 Go 问题提供 maps.Clear

    包在golang.org/x/exp/maps中找到(实验性,不在兼容性保证范围内)

    // Clear removes all entries from m, leaving it empty.
    func Clear[M ~map[K]V, K comparable, V any](m M)
    

    它的用法

    func main() {
        testMap := map[string]int{"gopher": 1, "badger": 2}
        maps.Clear(testMap)
        fmt.Println(testMap)
        
        testMap["zebra"] = 2000
        fmt.Println(testMap)
    }
    

    在此处运行代码 https://go.dev/play/p/qIdnGrd0CYs?v=gotip

    【讨论】:

      【解决方案5】:

      如果您尝试循环执行此操作,您可以利用初始化为您清除地图。例如:

      for i:=0; i<2; i++ {
          animalNames := make(map[string]string)
          switch i {
              case 0:
                  animalNames["cat"] = "Patches"
              case 1:
                  animalNames["dog"] = "Spot";
          }
      
          fmt.Println("For map instance", i)
          for key, value := range animalNames {
              fmt.Println(key, value)
          }
          fmt.Println("-----------\n")
      }
      

      执行此操作时,它会清除之前的地图并从空地图开始。输出验证了这一点:

      $ go run maptests.go 
      For map instance 0
      cat Patches
      -----------
      
      For map instance 1
      dog Spot
      -----------
      

      【讨论】:

      • 这不是清除地图,而是制作一个新地图并绑定到每个循环具有相同名称的局部变量。
      猜你喜欢
      • 2013-06-03
      • 1970-01-01
      • 2017-07-31
      • 1970-01-01
      • 1970-01-01
      • 2015-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多