Golang map类型的教程和实例

164 阅读6分钟

这篇文章涵盖了Golang地图类型的教程和实例

在我之前的文章中,涵盖了Golang中的地图指南

以下是Go语言中地图类型的例子

如何通过键或值对Map进行排序?

在Golang中,地图是由键值对组成的有序数据结构。

要对地图进行排序,我们必须写一个自定义的代码来处理这个问题。

例如,我们有一个字符串key和int values的map。打印地图会以随机的顺序返回地图数据,这个顺序是不能保证的。

func main() {  
 employees := map[string]int{"Kiran": 2030, "John": 10210,
  "Mark": 25000}  
 fmt.Println(employees)  
 fmt.Println(employees)  
 fmt.Println(employees)  
 fmt.Println(employees)  
 fmt.Println(employees)  
}  

输出是

map[John:10210 Mark:25000 Kiran:2030]  
map[John:10210 Mark:25000 Kiran:2030]  
map[Kiran:2030 John:10210 Mark:25000]  
map[Mark:25000 Kiran:2030 John:10210]  
map[Kiran:2030 John:10210 Mark:25000]  

现在,如何根据键值对地图进行排序

package main  
  
import (  
 "fmt"  
 "sort"  
)  
  
func main() {  
 employees := map[string]int{"Kiran": 2030, "John": 10210, "Mark": 25000}  
 fmt.Println(employees)  
  
 keys := make([]string, 0, len(employees))  
 for k := range employees {  
  keys = append(keys, k)  
 }  
 sort.Strings(keys)  
 for _, k := range keys {  
  fmt.Println(k, employees[k])  
 }  
}  

显示的地图是以键值排序的,输出是

map[Mark:25000 Kiran:2030 John:10210]  
John 10210  
Kiran 2030  
Mark 

如何用一个数组的地图创建一个嵌套地图类型

在这个例子中,你可以创建一个键为字符串、值为地图阵列的地图。 首先,使用make a function of literal语法创建一个带有地图阵列的地图。

 mapArraysMap := map[string][]map[string]string{  
  "kiran": {{"id": "1"}, {"name": "kiran"}},  
  "john":  {{"id": "2"}, {"name": "kiran"}},  
 }

这将创建一个键为字符串、值为数组的地图。 添加和删除元素的方式与普通地图相同。 使用数组地图的完整例子

package main  
  
import (  
 "fmt"  
)  
  
func main() {  
  
 //Create a Map with array of map  
 mapArraysMap := map[string][]map[string]string{  
  "kiran": {{"id": "1"}, {"name": "kiran"}},  
  "john":  {{"id": "2"}, {"name": "kiran"}},  
 }  
 fmt.Println(mapArraysMap)  
 fmt.Println("Original length: ", len(mapArraysMap))  
 //Adding an Array of Map values to map  
 mapArraysMap["frank"] = []map[string]string{{"id": "2"}, {"name": "kiran"}}  
 fmt.Println(mapArraysMap)  
 fmt.Println("length: ", len(mapArraysMap))  
 //Delete entry from Map  
 delete(mapArraysMap, "frank")  
 fmt.Println("length: ", len(mapArraysMap))  
  
}

输出是

map[3:Gef 1:ram 2:arun]  
map[kiran:[map[id:1] map[name:kiran]] john:[map[id:2] map[name:kiran]]]  
Original length:  2  
map[john:[map[id:2] map[name:kiran]] frank:[map[id:2] map[name:kiran]] kiran:[map[id:1] map[name:kiran]]]  
length:  3  
length:  2  

如何从Map转换Slice/Array?

Slice是一个动态数组,其长度在运行时增长。地图是一个具有键和值对的集合。地图在搜索、添加和删除方面有很好的性能,但在迭代方面就不行了。没有标准的API函数可以将字符串转换为地图,有时我们需要将Slice字符串转换为声明的字符串,并像下面这样用字符串字样初始化一个Slice。

//create a slice with string literal  
countries := []string{"india", "USA", "UK", "France"}  

同时创建一个Map,key是整数,value是字符串 迭代slice,要么是简单的for循环,要么是带范围的for循环 下面是一个完整的例子

package main  
  
import (  
 "fmt"  
)  
  
func main() {  
  
 //create a slice with string literal  
 countries := []string{"india", "USA", "UK", "France"}  
 fmt.Println(countries)  
 // Create and initilize a Map with make function  
 countriesMap := make(map[int]string)  
 // Iterate Slice  
 for i := 0; i < len(countries); i++ {  
  countriesMap[i] = countries[i]  
 }  
 fmt.Println(countriesMap)  
}  

输出是

[india USA UK France]  
map[2:UK 3:France 0:india 1:USA]  

由于Map是一个无序的数据结构,当你多次运行上述程序时,显示的数据顺序可能会改变。

如何将Map转换成数组的键/值/项片?

通常我们需要从Map类型中检索键、值或两者。
例如,我们有一个Map,其键和值是字符串类型。
下面的程序讲述了以下内容

  • 从Map中获取键的片断
  • 从Map中获取值的数组
  • 从Map中获取项目的键值切片

下面是一个将Map转换为键/值/项片的例子

package main  
  
import (  
 "fmt"  
)  
  
func main() {  
 // Create and intilize map with string literals - First Name - Last Name  
 names := map[string]string{  
  "kiran":  "Babu",  
  "John":   "Frank",  
  "Silver": "Stallin",  
 }  
 fmt.Println("Map   ", names)  
 fmt.Println("Key value ", names)  
  
 // Retrieve keys of slice from Map  
 keys := []string{}  
 for key, _ := range names {  
  keys = append(keys, key)  
 }  
 fmt.Println("Keys  ", keys)  
  
 // Retrieve values of slice from Map  
 values := []string{}  
 for _, value := range names {  
  values = append(values, value)  
 }  
 fmt.Println("Values ", values)  
  
 // Retrieve  slice of key-value pairs from Map  
 items := [][]string{}  
 for key, value := range names {  
  items = append(items, []string{key, value})  
 }  
 fmt.Println("Values ", items)  
  
}  

输出是

Map    map[kiran:Babu John:Frank Silver:Stallin]  
Key value  map[Silver:Stallin kiran:Babu John:Frank]  
Keys   [Silver kiran John]  
Values  [Frank Stallin Babu]  
Values  [[Silver Stallin] [kiran Babu] [John Frank]]  

将两个或多个地图合并为一个地图

没有标准的函数来合并或连接地图。我们必须写一个自定义函数来将多个地图合并成一个单一的地图。结果地图对于给定的键可能有多个值,所以值应该被声明为切片,然后输出map[string][]string类型的地图
以下是地图合并的过程

  • 迭代地图
  • 在每次迭代中,将源地图中的每个值追加到输出地图中给定键的slice中。
  • 一旦分片地图被追加,我们必须把这个分片分配给输出地图的给定键。
  • 这个过程允许输出地图中出现重复的元素

这里是完整的地图合并例子

package main  
  
import (  
 "fmt"  
)  
  
func main() {  
 m1 := map[string]string{"k1": "v1"}  
 m2 := map[string]string{"k2": "v2"}  
 m3 := map[string]string{"k1": "v3"}  
  
 output := mergeMaps(m1, m2, m3)  
 fmt.Println(output)  
  
}  
func mergeMaps(maps ...map[string]string) map[string][]string {  
 result := map[string][]string{}  
 for _, m := range maps {  
  for k, v := range m {  
   result[k] = append(result[k], v)  
  }  
 }  
 return res  
}  

上述程序的输出

map[id_1:[val_1 val_3] id_2:[val_2]]  

如何检查地图的键和值的类型 - Reflection API

我们可以使用标准反射API获得地图、键和值的类型 reflect.TypeOf()函数返回给定变量的动态类型 如果给定变量是nil接口,则返回nil
reflect.TypeOf().key()函数返回地图键的数据类型 如果给定类型不是地图类型,则抛出恐慌性错误
reflect.TypeOf().elem()函数返回地图值的数据类型 如果给定类型不是地图则抛出恐慌性错误 这里是一个完整例子

package main  
  
import (  
 "fmt"  
 "reflect"  
)  
  
func main() {  
  
 var mymap map[string]int  
 fmt.Println("Map Type: ", reflect.TypeOf(mymap))  
 fmt.Println("Map Key Type: ", reflect.TypeOf(mymap).Key())  
 fmt.Println("Map Value Type: ", reflect.TypeOf(mymap).Elem())  
  
 mapArraysMap := map[string][]map[string]string{  
  "kiran": {{"id": "1"}, {"name": "kiran"}},  
 }  
 fmt.Println("Map Type: ", reflect.TypeOf(mapArraysMap))  
 fmt.Println("Map Key Type: ", reflect.TypeOf(mapArraysMap).Key())  
 fmt.Println("Map Value Type: ", reflect.TypeOf(mapArraysMap).Elem())  
  
}  

输出是

Map Type:  map[string]int  
Map Key Type:  string  
Map Value Type:  int  
Map Type:  map[string][]map[string]string  
Map Key Type:  string  
Map Value Type:  []map[string]string  

将带有Map的结构类型转换为JSOn类型

我们声明了一个结构,其中每个元素都是标准的字符串对象,除了地址元素。地址元素是一个字符串的地图

type Employee struct {  
 Id      string            `json:"id,omitempty"`  
 Name    string            `json:"name,omitempty"`  
 Address map[string]string `json:"address,omitempty"`  
}  

我们将使用json.MarshalIndent()函数把这个结构转换为JSOn,以下是一个例子

package main  
  
import (  
 "encoding/json"  
 "fmt"  
)  
  
// Declare Struct type  
type Employee struct {  
 Id      string            `json:"id,omitempty"`  
 Name    string            `json:"name,omitempty"`  
 Address map[string]string `json:"address,omitempty"`  
}  
  
func main() {  
 // Initialized Struct and add data to it  
 var emp Employee  
 emp.Id = "1"  
 emp.Name = "Frank"  
 m := make(map[string]string)  
 emp.Address = m  
 emp.Address["city"] = "Newyork"  
 emp.Address["country"] = "USA"  
 emp.Address["zipcode"] = "92451"  
  
 var data []byte  
 // Convert struct to json  
 data, _ = json.MarshalIndent(emp, "", "    ")  
  
 fmt.Println(string(data))  
}  

输出是

{  
    "id": "1",  
    "name": "Frank",  
    "address": {  
        "Country": "USA",  
        "city": "Newyork",  
        "zipcode": "92451"  
    }  
}  

摘要

在这篇文章中,你学到了golang地图类型的例子