avatarUday Hiwarale

Summary

The provided web content offers a comprehensive guide on the use of maps in Go, detailing their structure, initialization, access, deletion, and comparison, as well as how to iterate over them and use different data types as keys.

Abstract

The article titled "The anatomy of maps in Go" on the undefined website delves into the map data structure, explaining it as a collection of key-value pairs. It outlines how maps differ from arrays and slices by allowing various data types as keys, not just integers. The syntax for defining a map is given, along with an explanation of why a nil map cannot hold data until it is initialized with the make function. The article also covers how to add data to a map, access values, check for the existence of keys, and determine the number of elements in a map using the len function. It highlights the delete function for removing elements and discusses the limitations of map comparisons, emphasizing that maps are unordered collections. The use of for range for iteration and the ability to use any comparable type as a key are also discussed. The article concludes by noting that maps are reference types and provides guidance on copying maps without sharing the same internal data structure.

Opinions

  • The author suggests that using a nil map is impractical until it is properly initialized, as it cannot store data.
  • The article implies that the len function is a straightforward way to check the number of elements in a map, similar to its use with arrays and slices.
  • The author expresses that the delete function simplifies the process of removing elements from a map, unlike the more complex methods required for slices.
  • The author points out that the inability to directly compare maps for equality is a limitation, but offers the reflect.DeepEqual function as a workaround.
  • The random order of map elements during iteration is presented as a characteristic to be aware of, not as a disadvantage.
  • The article emphasizes the importance of understanding that maps are reference types to avoid unintended shared data structures when copying or passing maps to functions.

GOLANG

The anatomy of maps in Go

A map is a composite data type that can hold data represented by key:value pairs.

(source: pexels.com)

☛ What is a map?

A map is like an array except, instead of an integer index, you can have string or any other data types as a key. An illustration of a map looks like

{
  stringKey: intValue,
  stringKey: intValue
  ...
}

The syntax to define a map is

var myMap map[keyType]valueType

Where keyType is the data type of map keys while valueType is the data type of map values. A map is a composite data type because it is composed of primitive data types (see variables lesson for primitive data types).

Let’s declare a simple map.

https://play.golang.org/p/Rv6dEDtbsoZ

In the above program, we have declared a map m which is empty, because zero-value of a map is nil. But the thing about nil map is, we can’t add values to it because like slices, map cannot hold any data, rather they reference the internal data structure that holds the data.

So, in the case of nil map, the internal data structure is missing and assigning any data to it will case runtime panic panic: assignment to entry in nil map. You can use nil map as a variable to store another non nil map.

☛ Creating an empty map

An empty map is like an empty slice with internal data structure defined so that we can use it to store some data. Like slice, we can use make function to create an empty map.

m := make(map[keyType]valueType)

Let’s create a simple map age in which we can save the age of people.

https://play.golang.org/p/mrQ_Hw0lZI0

In the above program, we have created an empty map age which holds int data and referenced by string keys. You can access or assign a value of a map using a key like map[key].

Using that information, we have assigned some age data of mina, john and mike. You can add as many values as you want, as map like slice can hold a variable number of elements.

☛ Initializing a map

Instead of creating empty map and assigning new data, we can create a map with some initial data, like array and slice.

https://play.golang.org/p/49br11mmkqx

☛ Accessing map data

In case array or slice, when you are trying to access out of index element (when the index does not exist), Go will throw an error. But not in case of map.

When you are trying to access the value by the key which is not present in the map, Go will not throw an error, instead, it will return zero value of valueType.

https://play.golang.org/p/fq6i39u8AeF

28 is correct because that’s the age of mina but since jessy is not in the map, Go will return 0 as zero-value of data type int is 0.

So, to check if a key exists in the map or not, Go provide another syntax that returns 2 values.

value, ok := m[key]

Let’s see the above example in a new syntax

https://play.golang.org/p/YYYT2qdiGue

So, we are getting extra information on whether a key exists or not. If the key exists, the second parameter will be true else it will be false.

☛ Length of map

We can find out how many elements contained in a map using len function, which we saw in array and slice.

https://play.golang.org/p/94LOJeBXfq7

💡 There is nothing like capacity in map because Go completely takes control of internal data structure of map. Hence don’t try to use cap function on map.

☛ Delete map element

Unlike slice where you need to use a hack to delete an element, Go provide easier function delete to delete map element. Syntax of a delete function is as following.

func delete(m map[Type]Type1, key Type)

delete function demands the first argument to be a map and the second argument to be a key value.

https://play.golang.org/p/i_M0xZ6jleP

💡 If the key does not exist in the map, like jessy in above example, Go will not throw an error while executing delete function.

☛ Maps comparison

Like slice, a map can be only compared with nil. If you are thinking to iterate over a map and match each element, you are in grave trouble. But if you are in dire need to compare two maps, use reflect package’s DeepEqual function (https://golang.org/pkg/reflect/).

☛ Map iteration

Since there are no index values in map, you can’t use simple for loop with incrementing index value until it hits the end. You need to use for range to do it.

https://play.golang.org/p/MbLYk17Zu6C

range in for loop will return key and value of map element. You can also use _ (blank identifier) to ignore either key or value in case you don't need it, just like array and slice.

💡 Order of retrieval of elements in map is random when used in for iteration. Hence there is no guarantee that each time, they will be in order. That also explains why we can’t compare two maps.

☛ Map with other data types

It’s not necessary that only string types should be the keys of a map. All comparable types such as boolean, integer, float, complex, string, etc. can also be keys. This should be very obvious, but boolean just blows my mind because boolean can only represent 2 values, either true or false. Let’s see what happens where we can use it.

https://play.golang.org/p/NbeIj54VdFS

I guess we found ourselves a use case for boolean key values. But what if we add duplicate keys.

https://play.golang.org/p/sOC6TpettrK

This also proves that we are not allowed to add duplicate keys in a map.

☛ Maps are referenced type

Like slice, map references an internal data structure. When you copy a map to a new map, the internal data structure is not copied, just referenced.

https://play.golang.org/p/n-U1AF4jy8M

As expected, ages map now has two elements because we deleted one element. Not only that, but we got the same change in age map as well. This proves that, like slice (but unlike an array), when you assign a variable with another map variable, they share the same internal structure.

To copy a map, you need to use for loop.

https://play.golang.org/p/uqwruAyVym4

In the above case, we haven’t copied the map but used map keys and values to store in a different map that implements its own underlying data structure.

💡 Since map references internal data structure, map passed as function parameter share same internal data structure just like slice. Hence, make sure to follow same guidelines as explained in the slices lesson.

(thatisuday.com / GitHub / Twitter/ StackOverflow / Instagram)
Programming
Go Programming
Go Programming Language
Golang
Golang Tutorial
Recommended from ReadMedium