百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

Go map详解 go map函数

liebian365 2024-10-25 15:40 12 浏览 0 评论

什么是map?

map是 Go 中的内置类型,用于存储键值对。让我们以一家只有几名员工的初创公司为例。为简单起见,我们假设所有这些员工的名字都是唯一的。我们正在寻找一种数据结构来存储每个员工的薪水。map将非常适合此用例。员工的名字可以是key,薪水可以是value。map类似于其他语言(如Python)的字典。

如何创建map?

可以通过将键和值的类型传递给make函数来创建map,以下是创建新map的语法。

make(map[type of key]type of value)  
employeeSalary := make(map[string]int)  

上面的代码行创建一个名为 employeeSalary 的map,其中包含字符串类型键和int类型值。完整代码如下:

package main

import (  
    "fmt"
)

func main() {  
    employeeSalary := make(map[string]int)
    fmt.Println(employeeSalary)
}

输出为:

map[]  

由于我们没有向Map添加任何元素,因此它是空的。

添加元素到map

向map添加新元素的语法与数组的语法相同。下面的程序将一些新员工添加到员工工资map中。

package main

import (  
    "fmt"
)

func main() {  
    employeeSalary := make(map[string]int)
    employeeSalary["steve"] = 12000
    employeeSalary["jamie"] = 15000
    employeeSalary["mike"] = 9000
    fmt.Println("employeeSalary map contents:", employeeSalary)
}

我们增加了steve、jamie和mike的三名员工以及他们相应的薪水。

上面的程序打印,

employeeSalary map contents: map[steve:12000 jamie:15000 mike:9000]  

也可以在声明本身期间初始化map。

package main

import (  
    "fmt"
)

func main() {  
    employeeSalary := map[string]int {
        "steve": 12000,
        "jamie": 15000,
    }
    employeeSalary["mike"] = 9000
    fmt.Println("employeeSalary map contents:", employeeSalary)
}

上面的程序声明了员工工资,并在声明本身中添加了两个元素。稍后又添加了一个带有键mike的元素。程序打印:

employeeSalary map contents: map[jamie:15000 mike:9000 steve:12000] 

不必只有字符串类型才是键。所有可比较的类型,例如布尔值,整数,浮点数,复数,字符串,...也可以是key。甚至用户定义的类型(如结构)也可以是键。

零值的map

map的零值为nil。如果尝试将元素添加到nil map,则会发生运行时崩溃。因此,必须在添加元素之前初始化map。

package main

func main() {  
    var employeeSalary map[string]int
    employeeSalary["steve"] = 12000
}

在上面的程序中,employeeSalary为nil,我们正在尝试向map添加新键。程序将因错误而panic。

panic: assignment to entry in nil map

从map中检索键的值

现在我们已经向map添加了一些元素,让我们学习如何检索它们。map[key] 是检索映射元素的语法。

package main

import (  
    "fmt"
)

func main() {  
    employeeSalary := map[string]int{
        "steve": 12000,
        "jamie": 15000,
        "mike": 9000,
    }
    employee := "jamie"
    salary := employeeSalary[employee]
    fmt.Println("Salary of", employee, "is", salary)
}

上面的程序非常简单。检索并打印员工jamie的工资。程序打印:

Salary of jamie is 15000  

如果元素不存在会发生什么?map将返回该元素类型的零值。在 employeeSalary map 的情况下,如果我们尝试访问一个不存在的元素,则将返回 int 的零值0。

package main

import (  
    "fmt"
)

func main() {  
    employeeSalary := map[string]int{
        "steve": 12000,
        "jamie": 15000,
    }
    fmt.Println("Salary of joe is", employeeSalary["joe"])
}

上面的程序输出:

Salary of joe is 0 

上述程序返回乔的薪水为 0。当我们尝试检索map中不存在的键的值时,不会有运行时错误。

检查key是否存在

上面,我们了解到当键不存在时,将返回该类型的零值。当我们想要找出键是否真的存在于map中时,这无济于事。

例如,我们想知道 employeeSalary map中是否存在键。

value, ok := map[key]  

以上是用于确定map中是否存在特定键的语法。如果ok为 true,则键存在,其值存在于变量值中,否则键不存在。

package main

import (  
    "fmt"
)

func main() {  
    employeeSalary := map[string]int{
        "steve": 12000,
        "jamie": 15000,
    }
    newEmp := "joe"
    value, ok := employeeSalary[newEmp]
    if ok == true {
        fmt.Println("Salary of", newEmp, "is", value)
        return
    }
    fmt.Println(newEmp, "not found")
}

在上面的程序中,在第13行中,ok将是假的,因为jo不存在。因此,程序将打印,

joe not found  

迭代map中的元素

range形式的for循环可以用来迭代map中的元素。

package main

import (  
    "fmt"
)

func main() {  
    employeeSalary := map[string]int{
        "steve": 12000,
        "jamie": 15000,
        "mike":  9000,
    }
    fmt.Println("Contents of the map")
    for key, value := range employeeSalary {
        fmt.Printf("employeeSalary[%s] = %d\n", key, value)
    }

}

上面的程序输出,

Contents of the map  
employeeSalary[mike] = 9000  
employeeSalary[steve] = 12000  
employeeSalary[jamie] = 15000  

一个重要的事实是,对于程序的每次执行,使用for range从映射中检索值的顺序不能保证相同,它也与元素添加到地map的顺序不同。

从map中删除元素

delete(map, key)是从map删除元素的语法。delete函数不返回任何值。

package main

import (  
    "fmt"
)

func main() {  
    employeeSalary := map[string]int{
        "steve": 12000,
        "jamie": 15000,     
        "mike": 9000,
    }
    fmt.Println("map before deletion", employeeSalary)
    delete(employeeSalary, "steve")
    fmt.Println("map after deletion", employeeSalary)
}

上面的程序删除key steve,并且运行输出:

map before deletion map[steve:12000 jamie:15000 mike:9000]  
map after deletion map[mike:9000 jamie:15000]  

如果我们尝试从map中删除不存在的key时,并不会产生运行时error。

结构体map

目前为止,我们仅仅存储了员工的薪水在map中。是否有种方式能够将每个员工的国籍也存储在map中。这可以通过使用struct map来实现。员工可以表示为包含字段工资和国籍的结构体,它们将使用字符串键和结构体值存储在map中。让我们编写一个程序来了解如何做到这一点。

package main

import (  
    "fmt"
)

type employee struct {  
    salary  int
    country string
}

func main() {  
    emp1 := employee{
        salary:  12000,
        country: "USA",
    }
    emp2 := employee{
        salary:  14000,
        country: "Canada",
    }
    emp3 := employee{
        salary:  13000,
        country: "India",
    }
    employeeInfo := map[string]employee{
        "Steve": emp1,
        "Jamie": emp2,
        "Mike":  emp3,
    }

    for name, info := range employeeInfo {
        fmt.Printf("Employee: %s Salary:$%d  Country: %s\n", name, info.salary, info.country)
    }

}

在上述程序中,员工结构包含字段工资和国籍。我们创建了三个员工 emp1、emp2 和 emp3。在第25行中,我们使用我们创建的三个员工初始化一个具有键类型字符串和值类型员工的map。map在第31行进行迭代,员工详细信息打印在下一行。该程序将打印,

Employee: Mike Salary:$13000  Country: India  
Employee: Steve Salary:$12000  Country: USA  
Employee: Jamie Salary:$14000  Country: Canada 

map的长度

map的长度可以通过len函数确定。

package main

import (  
    "fmt"
)

func main() {  
    employeeSalary := map[string]int{
        "steve": 12000,
        "jamie": 15000,
    }
    fmt.Println("length is", len(employeeSalary))

}

上面的程序会输出,

length is 2  

map是引用类型

类似于slice切片,map是引用类型,当一个map被赋给一个新的变量,则它们都指向同一个内存,因此,一个中所做的更改将反映在另一个中。

package main

import (  
    "fmt"
)

func main() {  
    employeeSalary := map[string]int{
        "steve": 12000,
        "jamie": 15000,     
        "mike": 9000,
    }
    fmt.Println("Original employee salary", employeeSalary)
    modified := employeeSalary
    modified["mike"] = 18000
    fmt.Println("Employee salary changed", employeeSalary)

}

在上述程序的第14行中,employeeSalary被分配给modified。在下一行中,在修改后的map中,mike的薪水更改为18000。程序输出,

Original employee salary map[jamie:15000 mike:9000 steve:12000]  
Employee salary changed map[jamie:15000 mike:18000 steve:12000]  

当map作为参数传递给函数时,情况也是如此。当对函数内的map进行任何更改时,调用方也将看到它。

map的比较

map不能通过==来进行比较。==仅仅可以用来检查map是否是nil值。

package main

func main() {  
    map1 := map[string]int{
        "one": 1,
        "two": 2,
    }

    map2 := map1

    if map1 == map2 {
    }
}

上面的程序会出现编译错误,

invalid operation: map1 == map2 (map can only be compared to nil)  

检查两个map是否相等的一种方法是逐个比较每个映射的各个元素。另一种方法是使用反射。你为可以为此编写一个程序,并使其:)工作。


总结:

1.map创建两种方式

make(map[type of key]type of value)

employeeSalary := map[string]int {“1”: 1}

2.for range迭代map;

3. if v, ok := map[key]; ok {}判断map中key是否存在;

4.delete(map, key)从map中删除元素;

5.len(map)得到map长度;

6.map是引用类型;

7.map可以通过reflect.DeepEqual()进行比较;

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: