golang的Map

Map集合

概述

Map 是一种无序的键值对的集合。

Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。

Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,遍历 Map 时返回的键值对的顺序是不确定的。

在获取 Map 的值时,如果键不存在,返回该类型的零值,例如 int 类型的零值是 0,string 类型的零值是 “”。

Map 是引用类型,如果将一个 Map 传递给一个函数或赋值给另一个变量,它们都指向同一个底层数据结构,因此对 Map 的修改会影响到所有引用它的变量。

定义map

map关键字定义

基本语法

var 集合名 map[键类型]值类型;

举例

package map_knowledge

import "fmt"

//通过关键字定义map
func CreateMap() {
	var map1  map[string]string;
	fmt.Printf("map1的值为%#v\n",map1)
}

结果

map1的值为map[string]string(nil)

注意

用关键字定义的map初始值为nil,我们不能对其直接操作。

package map_knowledge

import "fmt"

//通过关键字定义map
func CreateMap() {
	var map1  map[string]string;
	fmt.Printf("map1的值为%#v\n",map1)


	//用关键字定义的map为nil,不能直接操作
	/*
		报错:panic: assignment to entry in nil map
	*/
	// map1["name"] = "zhansan"
}

小结

这种用关键字定义的map就是一个空集合,如果要能够操作只有两种等价方案。

function CreateMap(){
    //方案1:定义完后用make开辟空间
    var map1 map[string]string
    map1 = make(map[string]string)
    
    //方案2:定义的时候赋值初始化
    //这样golang也会为map开辟空间
    var map2 = map[string]string{"name":"lisa"}
}

make定义

make既可以用于帮空集合开辟空间,也可以直接定义集合,golang官方也推荐这种形式。

基本语法

/* 使用 make 函数 */
map_variable := make(map[KeyType]ValueType, initialCapacity)

其中KeyType是键的类型,ValueType是值的类型,initialCapacity是可选的参数,用于指定 Map 的初始容量。

Map 的容量是指 Map 中可以保存的键值对的数量,当 Map 中的键值对数量达到容量时,Map 会自动扩容。

如果不指定 initialCapacity,Go 语言会根据实际情况选择一个合适的值。

一般来说我们不用特别指定容量,因为即使我们指定了,如果不够也会自己扩容。

举例

//通过make定义map
func CreateMapByMake(){
	var map1 = make(map[string]string,2)
	fmt.Printf("map1的值为%#v\n",map1)
}

结果

map1的值为map[string]string{}

注意

由于make定义开辟了空间,所以map可以直接操作。(这也是推荐用make定义的原因。)

func CreateMapByMake(){
	var map1 = make(map[string]string,2)
	fmt.Printf("map1的值为%#v\n",map1)

	map1["name"]="lisa"
	fmt.Printf("赋值后,map1的值为%#v\n",map1)
}

结果为

map1的值为map[string]string{}
赋值后,map1的值为map[string]string{"name":"lisa"}

map初始化

字面量初始化

基本语法

var map变量 map[键类型]值类型 = map[键类型]值类型{初始值}
//可以省略左边的类型
var map变量 = map[键类型]值类型{初始值}

map可以通过赋值直接初始化,例如:

var map1 = map[string]int{
    //最后一项也要有逗号
    "name":10,
}

注意事项

以字面量初始化map,内部的每一项用,隔开,且最后一项也必须要有,

make初始化

我们先查看make的源码:

func make(t Type, size ...IntegerType) Type

所以make只能先定义map,然后靠赋值初始化。

var map1 = make(map[string]int)
map1["age"] = 19

map访问

注意事项

我们只能操作开辟了内存空间的map,用关键字定义但是没有初始化的map是空map,无法操作.(见上文)

访问map

基本语法

map[keyValue];

访问不存在的键名不会报错,只会返回值类型的零值。

因为map[键类型]值类型,起初就指定了值的类型

举例

//访问map
func VisitMap(){
	var map1 = map[string]int{
		"age":19,
	}

	fmt.Printf("age的值为%#v\n",map1["age"])
	fmt.Printf("访问不存在的项值为%#v\n",map1["other"])
}

结果

age的值为19
访问不存在的项值为0

严格访问map

我们还可以用另一种方式访问map,来得知键是否存在。

基本语法

/*
	第一个返回值是键名对应的值,如果存在则返回值,否则为类型零值
	第二个返回值判断键是否存在,如果存在则是true,反之false
*/
val,isOk := map[键名] 

举例

func VisitMapIsOk(){
	var map1 = map[string]int{
		"age":19,
	}
	ageVal,isAgeOk := map1["age"]
	fmt.Printf("age存在为%v,age的值为%#v\n",isAgeOk,ageVal)

	nameVal,isNameOk := map1["name"]
	fmt.Printf("name存在为%v,name的值为%#v\n",isNameOk,nameVal)
}

结果

age存在为true,age的值为19
name存在为false,name的值为0

任意类型的值

我们可以用interface{}空接口类型来接收任意类型的值。

func InterfaceMap(){
    //interface{}是值类型
	var map1 = map[string]interface{}{
		"name":"lisa",
		"age":19,
	}
	for key, val := range map1 {
		fmt.Printf("键%v对应的值为%v\n",key,val)
	}
}

结果

键name对应的值为lisa
键age对应的值为19
注意事项1:零值

interface{}是一个字面量类型,被称为空接口类型,零值为<nil>

func InterfaceMap(){
	var map1 = map[string]interface{}{
		"name":"lisa",
		"age":19,
	}
	for key, val := range map1 {
		fmt.Printf("键%v对应的值为%v\n",key,val)
	}

	//注意事项1:interface{}是一个类型,零值为nil
	fmt.Printf("不存在的键的值为%v\n",map1["other"])
}

结果

键name对应的值为lisa
键age对应的值为19
不存在的键的值为<nil>
注意实现2:类型断言

interface{}类型的值在实际使用时需要类型断言,

断言语法

讲接口时会详述

var n interface{}
n = "world"
//val是值,ok代表是否成功
val,ok := n.(string)

如果断言出错也会报错,例如

func InterfaceMap(){
	var map1 = map[string]interface{}{
		"name":"lisa",
		"age":19,
	}
	for key, val := range map1 {
		fmt.Printf("键%v对应的值为%v\n",key,val)
	}

	//注意事项1:interface{}是一个类型,零值为nil
	fmt.Printf("不存在的键的值为%v\n",map1["other"])

	//注意事项2:interface{}类型的值在实际使用时要进行类型断言
	if(map1["age"].(int64)>=18){
		fmt.Printf("你已经是个成年人了")
	}
}

报错

panic: interface conversion: interface {} is int, not int64

正确案例

func InterfaceMap(){
	var map1 = map[string]interface{}{
		"name":"lisa",
		"age":19,
	}
	for key, val := range map1 {
		fmt.Printf("键%v对应的值为%v\n",key,val)
	}

	//注意事项1:interface{}是一个类型,零值为nil
	fmt.Printf("不存在的键的值为%v\n",map1["other"])

	//注意事项2:interface{}类型的值在实际使用时要进行类型断言
	/*
		可以先通过打印来判断具体类型,或者用switch方法
	*/
	fmt.Printf("键age的值类型为%T\n",map1["age"])
	if(map1["age"].(int)>=18){
		fmt.Printf("你已经是个成年人了")
	}
}

结果

键name对应的值为lisa
键age对应的值为19
不存在的键的值为<nil>
键age的值类型为int
你已经是个成年人了

map增改

基本语法

map[] =

如果键存在就是修改,否则就是新增。

map的长度

基本语法

len(map)

注意:不能用cap(map)求容量,因为map的容量用处不大,只是初始开辟空间时给个提示,未来可以轻松扩容。

举例

func GetMapLen(){
	var map1 = map[string]int{
		"age":19,
	}
	fmt.Printf("map1的长度为%d\n",len(map1))
}

结果

map1的长度为1

delete删除元素

基本语法

//要注意键的类型,golang是强类型语言
delete(map变量,键名)

举例

func DelMapItem(){
	var map1 = map[int64]string{
		1:"hello",
		2:"world",
	}

	fmt.Printf("删除前map1的值为%#v\n",map1)

	//删除
	delete(map1,1)
	fmt.Printf("删除后map1的值为%#v\n",map1)
}

结果

删除前map1的值为map[int64]string{1:"hello", 2:"world"}
删除后map1的值为map[int64]string{2:"world"}

注意事项

1.删除不存在的键不会报错。例如

func DelMapItem(){
	var map1 = map[int64]string{
		1:"hello",
		2:"world",
	}

	fmt.Printf("删除前map1的值为%#v\n",map1)

	//删除
	delete(map1,1)
	fmt.Printf("删除后map1的值为%#v\n",map1)

	//删除不存在的键,不会报错
	delete(map1,3)
}

2.被删除元素的影响

如果是map存在的元素:
1.map长度发生变化
2.map遍历时访问不到

但是我们仍然可以通过map[键名]访问到,返回值类型的零值,和之前一样。

但是用严格访问会提示为false.

map遍历

我们可以用for...range遍历map。

基本语法

for,:= range map{
    
}

举例

//遍历map
func RnageMap(){
	var map1 = map[int64]string{
		1:"hello",
		2:"world",
	}

	for key, val := range map1 {
		fmt.Printf("键%v对应的值为%v\n",key,val)
	}
}

结果

键1对应的值为hello
键2对应的值为world
### Golang Map Usage and Examples In the Go programming language, a `map` is an unordered collection of key-value pairs where each unique key maps to an associated value. Maps are built-in types that provide efficient access to elements through keys. To declare a map without initializing it immediately: ```go var countryCapitalMap map[string]string ``` Initialization can be done using the `make()` function or with a literal syntax when values are known at compile time[^1]: Using make(): ```go countryCapitalMap := make(map[string]string) ``` Literal initialization: ```go countryCapitalMap := map[string]string{ "France": "Paris", "Italy": "Rome", } ``` Adding entries into a map involves specifying both the key and its corresponding value as follows: ```go countryCapitalMap["India"] = "New Delhi" ``` Accessing data from within a map uses similar bracket notation but only requires providing the key part inside brackets followed by assignment operator if intending on retrieving stored information based off said identifier string provided earlier during creation phase above. Retrieving a value looks like this: ```go capital := countryCapitalMap["India"] fmt.Println(capital) // Output: New Delhi ``` Checking whether a specific element exists alongside getting back potential matching record(s): ```go value, exists := countryCapitalMap["Germany"] if !exists { fmt.Println("Key does not exist.") } else { fmt.Printf("The capital of Germany is %s\n", value) } ``` Deleting items out of collections such structures also adheres closely enough syntactically speaking whereby one would simply call delete passing along two arguments being firstly reference variable pointing towards target structure itself secondly actual item name whose presence needs removal operation performed upon accordingly thereafter. Removing an entry goes like so: ```go delete(countryCapitalMap, "France") ``` Iterating over all key-value pairs in a map utilizes range keyword which allows looping construct capable iterating across entire dataset contained therein efficiently while simultaneously unpacking current iteration's respective components (key & val). Looping example: ```go for key, value := range countryCapitalMap { fmt.Printf("%s -> %s\n", key, value) } ``` Maps support concurrent operations via goroutines safely under certain conditions however direct simultaneous read/write actions must still adhere strictly best practices guidelines outlined official documentation regarding synchronization primitives available package sync/atomic among others ensuring thread safety overall application design pattern employed throughout codebase development lifecycle stages involved hereafter[^2]. --related questions-- 1. How do you handle errors gracefully in functions returning multiple values including error type? 2. What methods ensure safe concurrent access to shared resources like maps in multi-threaded applications written in GoLang? 3. Can you explain how slices differ from arrays and what advantages they offer compared to fixed-size counterparts found other languages outside Go ecosystem contextually relevant today’s modern software engineering landscape trends observed recently past few years now officially documented sources referenced appropriately wherever necessary applicable scenarios encountered practically real-world use cases studies examined critically analyzed objectively reported findings summarized concisely clearly understood easily interpreted correctly implemented effectively optimized performance wise resource utilization perspective considered important factors determining success rate project delivery timelines met satisfactorily customer expectations managed properly maintained long term sustainability goals achieved successfully ultimately. 4. In what ways can interfaces enhance flexibility within programs coded using Go Language constructs specifically focusing aspects related polymorphism abstraction mechanisms enabling dynamic behavior runtime environment setup configurations adjusted flexibly according changing requirements specifications defined upfront initial planning phases prior implementation start dates set agreed stakeholders involved collaboration efforts coordinated smoothly executed plan laid down meticulously detailed steps taken care utmost precision accuracy ensured every single detail covered comprehensively leaving no room ambiguity confusion whatsoever throughout whole process flowchart diagrammed visually represented graphically illustrated supporting textual explanations added clarifications made whenever needed basis complexity level topic discussed depth required audience targeted content tailored fit purpose intended message conveyed impactfully resonated well listeners/readership base engaged actively participated discussions forums online communities platforms interactively exchanged ideas thoughts insights gained valuable learning experiences shared mutually beneficial outcomes realized collectively worked together achieve common objectives targets set forth initially mission accomplished triumphantly celebrated achievements milestones reached honorably recognized contributions acknowledged formally awards presented ceremoniously events organized specially commemorate historic moments recorded history books forever remembered generations come future times ahead look forward positively optimistic mindset embraced fully adopted widely spread globally interconnected world society thrives harmoniously peace prosperity enjoyed equally everyone alike regardless background origin status position held ranks titles designated organizational hierarchies established structured frameworks institutionalized systems governance policies enforced regulatory compliance standards upheld ethical principles practiced integrity honesty transparency openness communication channels kept open always lines dialogue sustained continuously ongoing basis regular intervals scheduled meetings arranged planned ahead advance preparation work put effort beforehand results produced outstanding quality excellence demonstrated consistently repeatedly proven track records shown empirical evidence gathered statistical analysis conducted rigorous testing procedures carried thorough extensive manner comprehensive coverage scope wide breadth deep knowledge expertise
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值