golang go语言_在Go中了解地图

golang go语言

Most modern programming languages have the concept of a dictionary or a hash type. These types are commonly used to store data in pairs with a key that maps to a value.

大多数现代编程语言都有字典哈希类型的概念。 这些类型通常用于与映射到成对存储数据。

In Go, the map data type is what most programmers would think of as the dictionary type. It maps keys to values, making key-value pairs that are a useful way to store data in Go. A map is constructed by using the keyword map followed by the key data type in square brackets [ ], followed by the value data type. The key-value pairs are then placed inside curly braces on either side { }:

在Go语言中, 地图数据类型是大多数程序员认为的字典类型。 它将键映射到值,形成键值对,这是在Go中存储数据的有用方法。 通过使用关键字map ,方括号[ ]的键数据类型以及值数据类型,来构建map 。 然后将键值对放在{}两侧的花括号内:

map[key]value{}

You typically use maps in Go to hold related data, such as the information contained in an ID. A map with data looks like this:

通常,您可以在Go中使用地图来保存相关数据,例如ID中包含的信息。 包含数据的地图如下所示:

map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}

In addition to the curly braces, there are also colons throughout the map that connect the key-value pairs. The words to the left of the colons are the keys. Keys can be any comparable type in Go, like strings, ints, and so on.

除了花括号外,整个地图中还存在连接键值对的冒号。 冒号左边的单词是键。 键可以是Go中任何可比较的类型,例如stringsints等等。

The keys in the example map are:

示例图中的键是:

  • "name"

    "name"

  • "animal"

    "animal"

  • "color"

    "color"

  • "location"

    "location"

The words to the right of the colons are the values. Values can be any data type. The values in the example map are:

冒号右边的单词是值。 值可以是任何数据类型。 示例映射中的值是:

  • "Sammy"

    "Sammy"

  • "shark"

    "shark"

  • "blue"

    "blue"

  • "ocean"

    "ocean"

Like the other data types, you can store the map inside a variable, and print it out:

与其他数据类型一样,您可以将地图存储在变量中,然后将其打印出来:

sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
fmt.Println(sammy)

This would be your output:

这将是您的输出:


   
Output
map[animal:shark color:blue location:ocean name:Sammy]

The order of the key-value pairs may have shifted. In Go, the map data type is unordered. Regardless of the order, the key-value pairs will remain intact, enabling you to access data based on their relational meaning.

键值对的顺序可能已经改变。 在Go中,地图数据类型是无序的。 无论顺序如何,键值对都将保持不变,从而使您能够根据它们的关系含义访问数据。

访问地图项 (Accessing Map Items)

You can call the values of a map by referencing the related keys. Since maps offer key-value pairs for storing data, they can be important and useful items in your Go program.

您可以通过引用相关键来调用地图的值。 由于地图提供了用于存储数据的键值对,因此它们在Go程序中可能是重要且有用的项目。

If you want to isolate Sammy’s username, you can do so by calling sammy["name"]; the variable holding your map and the related key. Let’s print that out:

如果要隔离Sammy的用户名,可以通过调用sammy["name"] ;来隔离。 存放地图的变量和相关键。 让我们打印出来:

fmt.Println(sammy["name"])

And receive the value as output:

并接收该值作为输出:


   
Output
Sammy

Maps behave like a database; instead of calling an integer to get a particular index value as you would with a slice, you assign a value to a key and call that key to get its related value.

地图的行为就像数据库; 您不必像使用切片那样调用整数来获取特定的索引值,而是将值分配给键并调用该键以获取其相关值。

By invoking the key "name" you receive the value of that key, which is "Sammy".

通过调用键"name"您将获得该键的值,即"Sammy"

Similarly you can call the remaining values in the sammy map using the same format:

同样,您可以使用相同的格式调用sammy地图中的其余值:

fmt.Println(sammy["animal"])
// returns shark

fmt.Println(sammy["color"])
// returns blue

fmt.Println(sammy["location"])
// returns ocean

By making use of the key-value pairs in map data types, you can reference keys to retrieve values.

通过使用地图数据类型中的键值对,您可以引用键来检索值。

键和值 (Keys and Values)

Unlike some programming languages, Go does not have any convenience functions to list out the keys or values of a map. An example of this would be Python’s .keys() method for dictionaries. It does, however, allow for iteration by using the range operator:

与某些编程语言不同,Go没有任何便利功能可以列出地图的键或值。 例如,Python的字典的.keys()方法。 但是,它确实允许使用range运算符进行迭代:

for key, value := range sammy {
    fmt.Printf("%q is the key for the value %q\n", key, value)
}

When ranging through a map in Go, it’ll return two values. The first value will be the key, and the second value will be the value. Go will create these variables with the correct data type. In this case, the map key was a string so key will also be a string. The value is also a string:

在Go中通过地图进行测距时,它将返回两个值。 第一个值为键,第二个值为键。 Go将使用正确的数据类型创建这些变量。 在这种情况下,映射键是一个string因此key也将是一个字符串。 该value也是一个字符串:


   
Output
"animal" is the key for the value "shark" "color" is the key for the value "blue" "location" is the key for the value "ocean" "name" is the key for the value "Sammy"

To get a list of just the keys, you can use the range operator again. You can declare just one variable to only access the keys:

要仅获取键列表,可以再次使用范围运算符。 您可以只声明一个变量以仅访问键:

keys := []string{}

for key := range sammy {
    keys = append(keys, key)
}
fmt.Printf("%q", keys)

The program begins by declaring a slice to store your keys in.

该程序首先声明一个切片来存储您的密钥。

The output will show only the keys of your map:

输出将仅显示地图的键:


   
Output
["color" "location" "name" "animal"]

Again, the keys are not sorted. If you want to sort them, you use the sort.Strings function from the sort package:

同样,键不排序。 如果要对它们进行排序,请使用sort包中的sort.Strings函数:

sort.Strings(keys)

With this function, you’ll receive the following output:

使用此功能,您将收到以下输出:


   
Output
["animal" "color" "location" "name"]

You can use the same pattern to retrieve just the values in a map. In the next example, you pre-allocate the slice to avoid allocations, thus making the program more efficient:

您可以使用相同的模式仅检索映射中的值。 在下一个示例中,您预先分配了切片以避免分配,从而使程序更高效:

sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}

items := make([]string, len(sammy))

var i int

for _, v := range sammy {
    items[i] = v
    i++
}
fmt.Printf("%q", items)

First you declare a slice to store your keys in; since you know how many items you need, you can avoid potential memory allocations by defining the slice at the exact same size. You then declare your index variable. As you don’t want the key, you use the _ operator, when starting your loop, to ignore the key’s value. Your output would be the following:

首先,您声明一个切片来存储您的密钥; 由于您知道需要多少个项目,因此可以通过以完全相同的大小定义切片来避免潜在的内存分配。 然后,您声明索引变量。 由于不需要键,因此在开始循环时可以使用_运算符来忽略键的值。 您的输出如下:


   
Output
["ocean" "Sammy" "shark" "blue"]

To determine the number of items in a map, you can use the built-in len function:

要确定地图中的项目数,可以使用内置的len函数:

sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
fmt.Println(len(sammy))

The output displays the number of items in your map:

输出显示地图中的项目数:


   
Output
4

Even though Go doesn’t ship with convenience functions to get keys and values, it only takes a few lines of code to retrieve the keys and values when needed.

即使Go并未附带便捷功能来获取键和值,但在需要时仅需要几行代码即可检索键和值。

检查存在性 (Checking Existence)

Maps in Go will return the zero value for the value type of the map when the requested key is missing. Because of this, you need an alternative way to differentiate a stored zero, versus a missing key.

当缺少要求的键时,Go中的Maps会传回地图值类型的零值。 因此,您需要一种替代方法来区分存储的零和丢失的键。

Let’s look up a value in a map that you know doesn’t exist and look at the value returned:

让我们在您知道不存在的映射中查找一个值,然后查看返回的值:

counts := map[string]int{}
fmt.Println(counts["sammy"])

You’ll see the following output:

您将看到以下输出:


   
Output
0

Even though the key sammy was not in the map, Go still returned the value of 0. This is because the value data type is an int, and because Go has a zero value for all variables, it returns the zero value of 0.

即使键sammy不在地图中,Go仍返回值0 。 这是因为value数据类型是int ,并且因为Go对于所有变量都具有零值,所以它将返回零值0

In many cases, this is undesirable and would lead to a bug in your program. When looking up the value in a map, Go can return a second, optional value. This second value is a bool and will be true if the key was found, or false if the key was not found. In Go, this is referred to as the ok idiom. Even though you could name the variable that captures the second argument anything you want, in Go, you always name it ok:

在许多情况下,这是不可取的,并且会导致程序中的错误。 在地图中查找值时,Go可以返回第二个可选值。 这第二个值是一个bool ,将是true ,如果钥匙被发现,或false如果该键没有被发现。 在Go中,这称为ok成语。 即使您可以命名捕获第二个参数的变量,也可以在Go中将其命名为ok

count, ok := counts["sammy"]

If the key sammy exists in the counts map, then ok will be true. Otherwise ok will be false.

如果在counts图中存在密钥sammy ,则oktrue 。 否则, ok将是错误的。

You can use the ok variable to decide what to do in your program:

您可以使用ok变量来决定要在程序中做什么:

if ok {
    fmt.Printf("Sammy has a count of %d\n", count)
} else {
    fmt.Println("Sammy was not found")
}

This would result in the following output:

这将导致以下输出:


   
Output
Sammy was not found

In Go, you can combine variable declaration and conditional checking with an if/else block. This allows you to use a single statement for this check:

在Go中,您可以将变量声明和条件检查与if / else块结合使用。 这使您可以使用单个语句进行此检查:

if count, ok := counts["sammy"]; ok {
    fmt.Printf("Sammy has a count of %d\n", count)
} else {
    fmt.Println("Sammy was not found")
}

When retrieving a value from a map in Go, it’s always good practice to check for its existence as well to avoid bugs in your program.

在Go中从地图中检索值时,最好同时检查其是否存在,以避免程序中的错误。

修改地图 (Modifying Maps)

Maps are a mutable data structure, so you can modify them. Let’s look at adding and deleting map items in this section.

地图是一种可变的数据结构,因此您可以对其进行修改。 让我们看看本节中添加和删除地图项。

添加和更改地图项 (Adding and Changing Map Items)

Without using a method or function, you can add key-value pairs to maps. You do this using the maps variable name, followed by the key value in square brackets [ ], and using the equal = operator to set a new value:

无需使用方法或函数,即可将键值对添加到地图。 您可以使用maps变量名称,然后在方括号[ ]输入键值,并使用equal =运算符设置新值:

map[key] = value

In practice, you can see this work by adding a key-value pair to a map called usernames:

实际上,您可以通过将键值对添加到名为usernames的映射中来查看此工作:

usernames := map[string]string{"Sammy": "sammy-shark", "Jamie": "mantisshrimp54"}

usernames["Drew"] = "squidly"
fmt.Println(usernames)

The output will display the new Drew:squidly key-value pair in the map:

输出将在地图中显示新的Drew:squidly键值对:


   
Output
map[Drew:squidly Jamie:mantisshrimp54 Sammy:sammy-shark]

Because maps are returned unordered, this pair may occur anywhere in the map output. If you use the usernames map later in your program file, it will include the additional key-value pair.

由于地图是按无序返回的,因此该对可能出现在地图输出中的任何位置。 如果稍后在程序文件中使用usernames映射,它将包含其他键值对。

You can also use this syntax for modifying the value assigned to a key. In this case, you reference an existing key and pass a different value to it.

您也可以使用此语法来修改分配给键的值。 在这种情况下,您引用现有的密钥,然后将一个不同的值传递给它。

Consider a map called followers that tracks followers of users on a given network. The user "drew" had a bump in followers today, so you need to update the integer value passed to the "drew" key. You’ll use the Println() function to check that the map was modified:

考虑一个称为followers的地图,该地图跟踪给定网络上用户的关注者。 今天,用户"drew"关注者人数激增,因此您需要更新传递给"drew"键的整数值。 您将使用Println()函数检查地图是否已修改:

followers := map[string]int{"drew": 305, "mary": 428, "cindy": 918}
followers["drew"] = 342
fmt.Println(followers)

Your output will show the updated value for drew:

您的输出将显示drew的更新值:


   
Output
map[cindy:918 drew:342 mary:428]

You see that the number of followers jumped from the integer value of 305 to 342.

您会看到关注者的数量从305的整数跃升至342

You can use this method for adding key-value pairs to maps with user input. Let’s write a quick program called usernames.go that runs on the command line and allows input from the user to add more names and associated usernames:

您可以使用此方法将键值对添加到具有用户输入的地图。 让我们编写一个名为usernames.go的快速程序,该程序在命令行上运行,并允许用户输入来添加更多名称和关联的用户名:

usernames.go
usernames.go
package main

import (
    "fmt"
    "strings"
)

func main() {
    usernames := map[string]string{"Sammy": "sammy-shark", "Jamie": "mantisshrimp54"}

    for {
        fmt.Println("Enter a name:")

        var name string
        _, err := fmt.Scanln(&name)

        if err != nil {
            panic(err)
        }

        name = strings.TrimSpace(name)

        if u, ok := usernames[name]; ok {
            fmt.Printf("%q is the username of %q\n", u, name)
            continue
        }

        fmt.Printf("I don't have %v's username, what is it?\n", name)

        var username string
        _, err = fmt.Scanln(&username)

        if err != nil {
            panic(err)
        }

        username = strings.TrimSpace(username)

        usernames[name] = username

        fmt.Println("Data updated.")
    }
}

In usernames.go you first define the original map. You then set up a loop to iterate over the names. You request your user to enter a name and declare a variable to store it in. Next, you check to see if you had an error; if so, the program will exit with a panic. Because Scanln captures the entire input, including the carriage return, you need to remove any space from the input; you do this with the strings.TrimSpace function.

usernames.go您首先定义原始地图。 然后,您设置一个循环以遍历名称。 您要求用户输入一个名称,并声明一个变量以将其存储在其中。接下来,检查是否有错误; 如果是这样,程序将以panic退出。 因为Scanln捕获整个输入,包括回车,所以您需要从输入中删除所有空间;因此, 您可以使用strings.TrimSpace函数执行此操作。

The if block checks whether the name is present in the map and prints feedback. If the name is present it then continues back to the top of the loop. If the name is not in the map, it provides feedback to the user and then will ask for a new username for the associated name. The program checks again to see if there is an error. With no error, it trims off the carriage return, assigns the username value to the name key, and then prints feedback that the data was updated.

if块检查名称是否存在于地图中并打印反馈。 如果存在名称,则继续返回循环顶部。 如果名称不在地图中,它将向用户提供反馈,然后将为关联的名称要求新的用户名。 程序再次检查是否有错误。 不会出现错误,它会修剪回车符,将用户名值分配给名称键,然后输出有关数据已更新的反馈。

Let’s run the program on the command line:

让我们在命令行上运行程序:

  • go run usernames.go

    去运行usernames.go

You’ll see the following output:

您将看到以下输出:


   
Output
Enter a name: Sammy "sammy-shark" is the username of "Sammy" Enter a name: Jesse I don't have Jesse's username, what is it? JOctopus Data updated. Enter a name:

When you’re done testing, press CTRL + C to escape the program.

完成测试后,按CTRL + C退出程序。

This shows how you can modify maps interactively. With this particular program, as soon as you exit the program with CTRL + C you’ll lose all your data unless you implement a way to handle reading and writing files.

这显示了如何交互地修改地图。 使用此特定程序,一旦您使用CTRL + C退出程序,您将丢失所有数据,除非您实现一种处理读写文件的方法。

To summarize, you can add items to maps or modify values with the map[key] = value syntax.

总而言之,您可以将项目添加到地图或使用map[key] = value语法修改值。

删除地图项 (Deleting Map Items)

Just as you can add key-value pairs and change values within the map data type, you can also delete items within a map.

正如您可以在地图数据类型中添加键值对和更改值一样,您也可以删除地图中的项目。

To remove a key-value pair from a map, you can use the built-in function delete(). The first argument is the map you are deleting from. The second argument is the key you are deleting:

要从地图中删除键值对,可以使用内置函数delete() 。 第一个参数是您要从中删除的地图。 第二个参数是要删除的键:

delete(map, key)

Let’s define a map of permissions:

让我们定义一个权限图:

permissions := map[int]string{1: "read", 2: "write", 4: "delete", 8: "create", 16:"modify"}

You no longer need the modify permission, so you’ll remove it from your map. Then you’ll print out the map to confirm it was removed:

您不再需要modify权限,因此将其从地图中删除。 然后,您将打印出地图以确认已将其删除:

permissions := map[int]string{1: "read", 2: "write", 4: "delete", 8: "create", 16: "modify"}
delete(permissions, 16)
fmt.Println(permissions)

The output will confirm the deletion:

输出将确认删除:


   
Output
map[1:read 2:write 4:delete 8:create]

The line delete(permissions, 16) removes the key-value pair 16:"modify" from the permissions map.

delete(permissions, 16)permissions映射中删除键/值对16:"modify"

If you would like to clear a map of all of its values, you can do so by setting it equal to an empty map of the same type. This will create a new empty map to use, and the old map will be cleared from memory by the garbage collector.

如果要清除所有值的映射,可以通过将其设置为等于相同类型的空映射来清除。 这将创建一个要使用的新的空映射,并且垃圾回收器将从内存中清除旧的映射。

Let’s remove all the items within the permissions map:

让我们删除permissions图中的所有项目:

permissions = map[int]string{}
fmt.Println(permissions)

The output shows that you now have an empty map devoid of key-value pairs:

输出显示您现在有了一个没有键值对的空映射:


   
Output
map[]

Because maps are mutable data types, they can be added to, modified, and have items removed and cleared.

由于地图是可变数据类型,因此可以将其添加,修改并删除和清除项目。

结论 (Conclusion)

This tutorial explored the map data structure in Go. Maps are made up of key-value pairs and provide a way to store data without relying on indexing. This allows us to retrieve values based on their meaning and relation to other data types.

本教程探讨了Go中的地图数据结构。 映射由键值对组成,并提供了一种无需依赖索引即可存储数据的方法。 这使我们能够根据值的含义以及与其他数据类型的关系来检索值。

翻译自: https://www.digitalocean.com/community/tutorials/understanding-maps-in-go

golang go语言

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值