由于近期个人原因导致更新停滞了,非常抱歉。另外后台数据显示前几篇文章的完整阅读率只有30%~40%,所以此后尽量压缩篇幅到之前的1/3,减少大家的阅读压力。

本篇讲解golang语言中的map数据结构,即由键值对构成的无序数据。map数据结构在python、java等多种语言中实现,其主要特点是能通过键(key)快速查询值(value)。

map的常见操作有:声明、赋值、添加、删除、查询、遍历、清空等

varstuMapmap[int]string  //声明 var map名称 map[键类型]值类型
mapScore:=make(map[string]float32) //或者这样声明
​
stuMap=map[int]string{1001:"Tom",1002:"Tim"} //赋值
stuMap[1003] ="Tem"       //添加
delete(stuMap, 1003)        //删除
​
data, flag:=stuMap[1003] //查询该数据是否存在,不存在时flag为false;存在时  
                                   //data存储数据,flag为true
​
forkey, data:=rangestuMap{ //遍历键和值
   fmt.Println(key, data)
   delete(stuMap, key)        //循环删除清空
}
stuMap=make(map[int]string)  //或者重新make新的空间以清空stuMap,推荐方法

map的常见方法有:键值存在性、排序、嵌套

data, flag:=stuMap[1003] //判断存在性,查询该数据是否存在,不存在时flag为false;存在时  
                                   //data存储数据,flag为true
​
import"sort"                 //利用sort包完成排序功能
varsortSlice[]int            //定义sortSlice切片
   forkey, _:=rangestuMap{
   sortSlice=append(sortSlice, key) //合成切片
} 
sort.Ints(sortSlice)
varstuMap2map[int](map[int]string) //嵌套,即值类型可以嵌套其他类型

map的基本操作就是这样,这里有2个地方需要注意:

第一、map为引用类型,传递参数的时候传递引用,而不是值传递,所以修改后外部是会改变的。

第二、map的内部存储结构是可能重新组织的,比如大量数据需要优化树状结构时会引起map存储结构改变。也就是说对某个具体的数据取地址是可能改变的,之后使用按址查询的时候可能查询错误,所以不能直接对map的元素取地址

sync.Map

在go的并发编程中,不可避免的要考虑线程安全性问题;针对map数据结构,golang提供sync.Map保证线程安全。具体的实现原理这里先不讲解,目前主要讲解用法。如下所示,使用sync.Map类型保证线程安全,所以在并发中使用map数据类型时应选择sync.Map。

package main

import "fmt"
import "sync"
import "time"

func main(){
  var mTest sync.Map
  go SyncTest(mTest)
  go SyncTest(mTest)
  time.Sleep(time.Second * 20)
}

func SyncTest(mTest sync.Map){
    for j := 0; j < 1000; j++{
        fmt.Println(mTest.Load("A"))//Load 读取
        mTest.Store("A", "a") //Store 存储
        fmt.Println(mTest.Load("A"))
        mTest.Delete("A") //Delete 删除
        fmt.Println(mTest.Load("A"))
        mTest.LoadOrStore("B","b") //LoadOrStore 读取失败则存储
        fmt.Println(mTest.Load("B"))
    }    
}