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

Go map详解 go map函数

liebian365 2024-10-25 15:40 18 浏览 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()进行比较;

相关推荐

“版本末期”了?下周平衡补丁!国服最强5套牌!上分首选

明天,酒馆战棋就将迎来大更新,也聊了很多天战棋相关的内容了,趁此机会,给兄弟们穿插一篇构筑模式的卡组推荐!老规矩,我们先来看10职业胜率。目前10职业胜率排名与一周前基本类似,没有太多的变化。平衡补丁...

VS2017 C++ 程序报错“error C2065:“M_PI”: 未声明的标识符"

首先,程序中头文件的选择,要选择头文件,在文件中是没有对M_PI的定义的。选择:项目——>”XXX属性"——>配置属性——>C/C++——>预处理器——>预处理器定义,...

东营交警实名曝光一批酒驾人员名单 88人受处罚

齐鲁网·闪电新闻5月24日讯酒后驾驶是对自己和他人生命安全极不负责的行为,为守护大家的平安出行路,东营交警一直将酒驾作为重点打击对象。5月23日,东营交警公布最新一批饮酒、醉酒名单。对以下驾驶人醉酒...

Qt界面——搭配QCustomPlot(qt platform)

这是我第一个使用QCustomPlot控件的上位机,通过串口精确的5ms发送一次数据,再将读取的数据绘制到图表中。界面方面,尝试卡片式设计,外加QSS简单的配了个色。QCustomPlot官网:Qt...

大话西游2分享赢取种族坐骑手办!PK趣闻录由你书写

老友相聚,仗剑江湖!《大话西游2》2021全民PK季4月激燃打响,各PK玩法鏖战齐开,零门槛参与热情高涨。PK季期间,不仅各种玩法奖励丰厚,参与PK趣闻录活动,投稿自己在PK季遇到的趣事,还有机会带走...

测试谷歌VS Code AI 编程插件 Gemini Code Assist

用ClaudeSonnet3.7的天气测试编码,让谷歌VSCodeAI编程插件GeminiCodeAssist自动编程。生成的文件在浏览器中的效果如下:(附源代码)VSCode...

顾爷想知道第4.5期 国服便利性到底需优化啥?

前段时间DNF国服推出了名为“阿拉德B计划”的系列改版计划,截至目前我们已经看到了两项实装。不过关于便利性上,国服似乎还有很多路要走。自从顾爷回归DNF以来,几乎每天都在跟我抱怨关于DNF里面各种各样...

掌握Visual Studio项目配置【基础篇】

1.前言VisualStudio是Windows上最常用的C++集成开发环境之一,简称VS。VS功能十分强大,对应的,其配置系统较为复杂。不管是对于初学者还是有一定开发经验的开发者来说,捋清楚VS...

还嫌LED驱动设计套路深?那就来看看这篇文章吧

随着LED在各个领域的不同应用需求,LED驱动电路也在不断进步和发展。本文从LED的特性入手,推导出适合LED的电源驱动类型,再进一步介绍各类LED驱动设计。设计必读:LED四个关键特性特性一:非线...

Visual Studio Community 2022(VS2022)安装图文方法

直接上步骤:1,首先可以下载安装一个VisualStudio安装器,叫做VisualStudioinstaller。这个安装文件很小,很快就安装完成了。2,打开VisualStudioins...

Qt添加MSVC构建套件的方法(qt添加c++11)

前言有些时候,在Windows下因为某些需求需要使用MSVC编译器对程序进行编译,假设我们安装Qt的时候又只是安装了MingW构建套件,那么此时我们该如何给现有的Qt添加一个MSVC构建套件呢?本文以...

Qt为什么站稳c++GUI的top1(qt c)

为什么现在QT越来越成为c++界面编程的第一选择,从事QT编程多年,在这之前做C++界面都是基于MFC。当时为什么会从MFC转到QT?主要原因是MFC开发界面想做得好看一些十分困难,引用第三方基于MF...

qt开发IDE应该选择VS还是qt creator

如果一个公司选择了qt来开发自己的产品,在面临IDE的选择时会出现vs或者qtcreator,选择qt的IDE需要结合产品需求、部署平台、项目定位、程序猿本身和公司战略,因为大的软件产品需要明确IDE...

Qt 5.14.2超详细安装教程,不会来打我

Qt简介Qt(官方发音[kju:t],音同cute)是一个跨平台的C++开库,主要用来开发图形用户界面(GraphicalUserInterface,GUI)程序。Qt是纯C++开...

Cygwin配置与使用(四)——VI字体和颜色的配置

简介:VI的操作模式,基本上VI可以分为三种状态,分别是命令模式(commandmode)、插入模式(Insertmode)和底行模式(lastlinemode),各模式的功能区分如下:1)...

取消回复欢迎 发表评论: