• Golang 快速删除map所有元素


    1. 所有Go版本通用方法:

    重新申请一个新的map,旧的map交给GC去回收。

    a := make(map[string]int)
    
    a["a"] = 1
    a["b"] = 2
    
    // clear all
    a = make(map[string]int)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2. Go 1.11版本以上用法:

    通过Go的内部函数mapclear方法删除。这个函数并没有显示的调用方法,当你使用for循环遍历删除所有元素时,Go的编译器会优化成Go内部函数mapclear。

    package main
    
    func main() {
            m := make(map[byte]int)
    
            m[1] = 1
            m[2] = 2
    
            for k := range m {
    	        delete(m, k)
            }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    把上述源代码直接编译成汇编(默认编译是会优化的):

    go tool compile -S map_clear.go
    
    • 1

    可以看到编译器把源码9行的for循环直接优化成了mapclear去删除所有元素。如下:
    在这里插入图片描述
    再来看看关闭优化后的结果:

    go tool compile -l -N -S map_clear.go
    
    • 1

    关闭优化选项后,Go编译器直接通过循环遍历来删除map里面的元素。
    在这里插入图片描述
    由上可知,遍历删除在经过编译器优化后会调用mapclear一次性删除map所有元素,那这个mapclear函数是如何实现的,效率如何?

    mapclear源码实现

    这部分代码涉及到内存管理和GC,只能看懂个大概,后续再补充。

    实现思路:

    • 清空统计数据,如元素个数、溢出数等。

    • 重新申请一个新的extra,原有的extra交给GC。

    • 释放桶内存块。

      func mapclear(t *maptype, h *hmap) {

      // 把oldbuckets置nil,如果有oldbuckets就让GC处理
      h.oldbuckets = nil
      
      // 初始化溢出数、元素个数
      h.nevacuate = 0
      h.noverflow = 0
      h.count = 0	
      
      // 重新申请一个新的extra,旧的交给GC回收
      if h.extra != nil {
      	*h.extra = mapextra{}
      }
      
      // 清空bucket
      _, nextOverflow := makeBucketArray(t, h.B, h.buckets)
      ...
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

      }

      func makeBucketArray(t *maptype, b uint8, dirtyalloc unsafe.Pointer) (buckets unsafe.Pointer, nextOverflow *bmap) {
      base := bucketShift(b)
      nbuckets := base

      // 没有分配过内存,则申请一个新的
      if dirtyalloc == nil {
      	buckets = newarray(t.bucket, int(nbuckets))
      } else {
      	// 直接释放整个buckets
      	buckets = dirtyalloc
      	size := t.bucket.size * nbuckets
      	if t.bucket.kind&kindNoPointers == 0 {
      		memclrHasPointers(buckets, size)
      	} else {
      		memclrNoHeapPointers(buckets, size)
      	}
      }
      ...
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14

      }

    总结:
    使用mapclear方法清空map时,做的工作就是初始化和释放申请内存块,效率很高。

  • 相关阅读:
    java多线程基础技术
    洛谷题单 Part2.1 模拟
    three.js世界坐标系和设备坐标系
    Linux安装Net7SDK运行Net项目
    vue和react的区别
    算法与数据结构-Trie树
    爬虫项目-爬取股吧(东方财富)评论
    victoriaMetrics库之布隆过滤器
    Go的优雅退出
    stm32之31.iic
  • 原文地址:https://blog.csdn.net/m0_67401499/article/details/126364171