go语言---map

go语言---map

https://blog.csdn.net/cyk2396/article/details/78890185

一.map的用法:

type PersonDB struct {
    Id      string
    Name    string
    Address string
}

fmt.Println("=========Map===========")
    //map是一堆键值对的未排序集合,在golang中是内置类型,可以直接使用,不像Java需要引入HashMap
    var personMap map[string]PersonDB                                 //声明一个map变量,string是键的类型,PersonDB是值的类型
    personMap = make(map[string]PersonDB, 10)                         //创建一个map,初始容量为10
    personMap["1"] = PersonDB{Id: "1", Name: "zs", Address: "北京市房山区"} //给map元素赋值
    personMap["2"] = PersonDB{Id: "2", Name: "ls", Address: "北京市海淀区"}
    //使用内置函数delete删除personMap中key="1"的元素,如果找不到该key,则什么也不会发生,如果personMap为nil,则抛错
    delete(personMap, "1")
    if value, ok := personMap["2"]; ok { //找到key=2的元素,则ok=true,value为找到的值;否则ok=false
        fmt.Println(value)
    }

    personMap2 := map[string]PersonDB{"3": PersonDB{"3", "ww", "杭州市西湖区"}} //创建并初始化一个map
    personMap2["4"] = PersonDB{"4", "ll", "北京市东城区"}
    for k, v := range personMap2 { //使用range遍历map中的元素
        fmt.Println(k, v)
        if k == "3" {
            v.Name = "wwUpdate"
            personMap2["3"] = v //可更改value值
            //以下这种赋值方式会报错,只能对value赋值,不能直接更改其成员变量
            // personMap2["3"].Name = "wwUpdate" //cannot assign to struct field personMap2["3"].Name in map
        }
    }
    fmt.Println(personMap2)

输出结果:
fatal error: concurrent map writes
由结果可知:map不是线程安全的。
至于为什么不是线程安全,以后再分析

三.map传值还是传引用?

运行以下代码:

//map传值还是传引用? map和slice,channel一样,内部都有一个指向真正存储空间的指针,所以,即使传参时是对值的复制(传值),但都指向同一块存储空间。
    var myMapV map[string]int
    var myMap1 map[string]int
    myMapV = map[string]int{"value": 0}
    myMap1 = myMapV
    fmt.Println("m =", myMapV)
    fmt.Println("m1 =", myMap1)
    myMap1["value"] = 1
    fmt.Println("m =", myMapV)
    fmt.Println("m1 =", myMap1)

二.map是线程安全的吗?

运行以下代码:


//map不是线程安全的。
     cMap := make(map[string]int)
    for i := 0; i < 100; i++ {
        go func() {
            for j := 0; j < 100; j++ {
            cMap[fmt.Sprintf("%d", j)] = j //fatal error: concurrent map writes
            }
        }()
    }
     time.Sleep(3 * time.Second)

输出结果:
m = map[value:0]
m1 = map[value:0]
m = map[value:1]
m1 = map[value:1]
我们发现,当修改了m1,m也随着改变了,这看似是传引用,但其实map也是传值的,它的原理和数组切片类似。map内部维护着一个指针,该指针指向真正的map存储空间。我们可以将map描述为如下结构:

type map[key]value struct{
impl *Map_K_V
}
type Map_K_V struct{
//......
}
其实,map和slice,channel一样,内部都有一个指向真正存储空间的指针,所以,即使传参时是对值的复制(传值),但都指向同一块存储空间。

原文地址:https://www.cnblogs.com/Leo_wl/p/9280847.html

时间: 2024-11-07 17:00:42

go语言---map的相关文章

Go语言Map的使用

Go 语言Map(集合) Map 是一种无序的键值对的集合.Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值. Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它.不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的. 定义 Map 可以使用内建函数 make 也可以使用 map 关键字来定义 Map: 声明变量,默认map是nilvar map_name = map[type]type 另外一种使用make

Go语言 map遍历

1 遍历顺序 Go语言里的map,是不保证遍历顺序的(这一点很好理解).甚至同样内容的map,两次遍历的顺序,也可能不一样.下面是一个例子: m := map[string]int{"a1": 1,"b2": 10,"c3": 2,} for k, v := range m {fmt.Printf("%s=%d;", k, v)} // c3=2;a1=1;b2=10; println() for k, v := range

Go语言 map的实现

Go中的map在底层是用哈希表实现的,你可以在 $GOROOT/src/pkg/runtime/hashmap.goc 找到它的实现. 数据结构 哈希表的数据结构中一些关键的域如下所示: struct Hmap { uint8 B; // 可以容纳2^B个项 uint16 bucketsize; // 每个桶的大小 byte *buckets; // 2^B个Buckets的数组 byte *oldbuckets; // 前一个buckets,只有当正在扩容时才不为空 }; 上面给出的结构体只是

【转】GO语言map类型interface{}转换踩坑小记

原文:https://www.az1314.cn/art/69 ------------------------------------------ mapA := make([string]interface{}) mapB := make([string]interface{}) mapA["name"] = "小文" mapA["age"]  = 25 mapB["mapA"] = mapA for k, v := ra

【Go语言】map在goroutine通信中的使用

简介 本篇文章的主要内容是解决go语言map在使用中遇到的两个问题 一.cannot assign to struct field https://haobook.readthedocs.io/zh_CN/latest/periodical/201611/zhangan.html 二.fatal error:concurrent map read and map write https://blog.csdn.net/skh2015java/article/details/60334091 原文

go语言基础教程

Go 是一个开源的编程语言,它能让构造简单.可靠且高效的软件变得容易. Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本.现在Go的开发已经是完全开放的,并且拥有一个活跃的社区. Go 语言环境安装 Go 语言支持以下系统: Linux FreeBSD Mac OS X(也称为 Darwin)

【GoLang笔记】遍历map时的key随机化问题及解决方法

之前的一篇笔记曾分析过,Go的map在底层是用hashmap实现的.由于高效的hash函数肯定不是对key做顺序散列的,所以,与其它语言实现的hashmap类似,在使用Go语言map过程中,key-value的插入顺序与遍历map时key的访问顺序是不相同的.熟悉hashmap的同学对这个情况应该非常清楚. 所以,本文要提到的肯定不是这个,而是一个比较让人惊奇的情况,下面开始说明. 1. 通过range遍历map时,key的顺序被随机化 在golang 1.4版本中,借助关键字range对Go语

Go语言开发(三)、Go语言内置容器

Go语言开发(三).Go语言内置容器 一.Go语言数组 1.Go语言数组简介 Go语言提供了数组类型的数据结构.数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,类型可以是任意的原始类型例如×××.字符串或者自定义类型.相对于去声明number0, number1, ..., and number99的变量,使用数组形式numbers[0], numbers[1] ..., numbers[99]更加方便且易于扩展.数组元素可以通过索引(位置)来读取(或者修改),索引从0开始,第一个元素

15. Go 语言“避坑”与技巧

Go 语言"避坑"与技巧 任何编程语言都不是完美的,Go 语言也是如此.Go 语言的某些特性在使用时如果不注意,也会造成一些错误,我们习惯上将这些造成错误的设计称为"坑". Go 语言的一些设计也具有与其他编程语言不一样的特性,能优雅.简单.高效地解决一些其他语言难以解决的问题. 本章将会对 Go 语言设计上可能发生错误的地方及 Go 语言本身的使用技巧进行总结和归纳. goroutine(Go语言并发)如何使用才更加高效? Go语言原生支持并发是被众人津津乐道的特