Go (Golang) Maps Explained

By
Vladimir Kaplarevic
Published:
July 31, 2025
Topics:

A hash table is one of the most efficient data structures for storing, searching, and deleting key-value pairs. In Go (Golang), this functionality is handled internally by the map data type.

Maps are commonly used in Go applications to perform in-memory CRUD (Create, Read, Update, Delete) operations on real-world data, such as user settings or product catalogs.

In this guide, you will learn how to use maps in Go to store key-value pairs in memory and reduce unnecessary database queries.

Article explains how Go maps work.

Prerequisites

What Is a Golang Map?

Golang maps are built-in data types that store collections of key-value pairs. Each key is unique and maps exactly to one value.

Go maps rely on a hash function to:

  • Convert each key into a hash value.
  • Use the hash value to compute an index in the internal data structure.
  • Store the key-value pair in an internal array at the calculated index.
  • Automatically handle collisions and optimize performance behind the scenes.

Unlike databases, maps do not require complex relationships, joins, or indexing. They are lightweight, fast, and easy to use for in-memory data access.

Note: Since maps are in-memory data structures, their content exists only while the application is running. Once the program stops, all data stored in Go maps is lost.

Go maps are best suited for temporary, fast-access storage. Use maps when you need to:

  • Quickly look up, delete, or insert data.
  • Temporarily store in-session user data.
  • Count page visits or similar short-term metrics.
  • Cache API requests and responses.
  • Store simple pairs such as product-to-price or user ID-to-name mappings.
  • Simulate real scenarios during development by using test fixtures and mock data as stand-ins.

Note: Maps are not suitable for persistent storage. For long-term data retention, you still need to use a database or filesystem.

Golang Map Syntax

The basic syntax for declaring a map type in Go is:

map[KeyType]ValueType{}

This defines a map type with a specific key type and value type, but it does not create a usable map or allocate memory.

To create and initialize a map with actual data, you need to use the make() function or a composite literal.

Golang Map Example

Go is a compiled language, which means you cannot run commands interactively. When working from the command line, it's necessary to write code in a file and then run that file using the go run command.

In the following example, an online store sells video games and wants to establish a map of product names and prices, and then calculate the total price.

To create and run the map:

1. Open a file with the .go extension using a preferred command-line text editor. For example, Nano:

nano gamePrices.go

2. Paste the following code:

package main

import "fmt"

func main() {
    // Create and initialize a map of products and their prices
    gamePrices := map[string]float64{
        "Baldurs Gate 3":             69.99,
        "Cyberpunk 2077":             59.99,
        "Divinity: Original Sin II":  49.99,
        "The Witcher 3: Wild Hunt":   40.00,
    }

    var total float64 = 0

    // Print all products and prices, and calculate the total
    fmt.Println("Product list:")
    for name, price := range gamePrices {
        fmt.Printf("- %s: $%.2f\n", name, price)
        total += price
    }

    // Print total price
    fmt.Printf("\nTotal price of all products: $%.2f\n", total)
}

The code declares a gamePrices map with string keys (video game titles) and float64 values (prices). Additionally, it iterates over the map to print each game's name and price and calculates the total price.

3. Save and close the file.

4. Run the file from the terminal:

go run gamePrices.go
Go map price calculation example.

The terminal displays the product list with individual prices and the total price at the end.

How to Create Golang Maps

When you create a map, Go sets up the internal structure and prepares it to store key-value pairs.

The most common way to create a map is by using the make() function. Other methods include using the var keyword or the short variable declaration syntax (:=) combined with composite literals.

Create Maps via make() Function

The make() function creates a fully initialized map, ready for read and write operations. Go handles the underlying hash table and memory allocation automatically. The following example creates a map called productPrice:

productPrice := make(map[string]float64)
productPrice["product1"] = 69.99
productPrice["product2"] = 49.99

The keys are defined as string, and the values are of type float64. Two product-price pairs have been added to the map.

Create Maps via var and :=

You can also create and initialize maps using the var keyword or the short declaration := together with composite literals. Composite literals allow users to create a map and populate it with key-value pairs in a single step.

The following example declares a map using var and initializes it with two product-price pairs:

var productPrice = map[string]float64{
     "product1":   69.99,
     "product2":   49.99,
}

In this code example, the := short declaration is used to declare and initialize the productPrice map in one step:

productPrice := map[string]float64{
    "product1": 69.99,
    "product2": 49.99,
}

These methods are useful when the initial data is known in advance, such as default configurations, lookup tables, or test data.

Create Empty Maps

When the data is not known in advance, it may be necessary to create an empty map and populate it later. The make() function is the preferred way to create empty maps, as it fully initializes the map and prepares it for write operations.

Apply the following syntax to create a map using the make() function:

productPrice := make(map[string]float64)

Then, add key-value pairs to the map when the values become available:

productPrice [product4] = 69.99
productPrice [product5] = 49.99

Because the map is already initialized, no additional steps are needed before adding or modifying entries.

Note: Declaring a map with var without initializing it results in a nil map. Assigning values to an uninitialized nil map causes a runtime panic.

Allowed and Not Allowed Map Keys

Map keys in Go must be unique, and the data types must be comparable (support == and != operators). The following table lists which data types can and cannot be used as keys:

Allowed Key TypesNot Allowed Key Types
int, int32, int64Slices
float32, float64Maps
stringFunctions
boolChannels
runeStruct with non-comparable fields
Arrays with comparable elementsArrays with non-comparable fields
Struct with comparable fields
Pointers

Allowed Map Values

The value in a key-value pair can store any type of data, including strings, numbers, JSON, or binary objects. Developers can utilize a wide range of data types without being constrained by a rigid schema.

Allowed map values include:

Allowed Data TypesExamples
Basic typesint, float64, string, bool
Structsstruct{X int; Y int}
Slices[]string, []float64
Mapsmap[string]int
Pointers*int, *MyStruct
Interfacesinterface{}
Custom typestype Age int, type Status string
JSON/binary representations[]byte, JSON-encoded values as string

Operations with Maps

The following examples show how a video game store uses a Go map to store product names and prices, and how it calculates totals and discounts in memory without relying on a database.

Iterate Through a Map

The following Go code example:

  • Declares the gamePrices map that stores video game titles as keys and their prices as values.
  • Applies a flat 10% discount to all existing prices.
  • Uses the range keyword to iterate over each key-value pair, calculate the new discounted price, and update the map.
  • Prints the updated values to the terminal.
package main

import "fmt"

func main() {
    // Original product prices
    gamePrices := map[string]float64{
        "Baldurs Gate 3":             69.99,
        "Cyberpunk 2077":             59.99,
        "Divinity: Original Sin II":  49.99,
        "The Witcher 3: Wild Hunt":   40.00,
    }

    discountRate := 0.10 // 10% discount

    // Apply discount to each product
    for name, price := range gamePrices {
        discountedPrice := price * (1 - discountRate)
        gamePrices[name] = discountedPrice
    }

    // Print updated prices
    fmt.Println("Discounted product prices:")
    for name, price := range gamePrices {
        fmt.Printf("- %s: $%.2f\n", name, price)
    }
}

This type of logic is typical in e-commerce systems when applying promotional offers, cart discounts, or limited-time offers.

Iterating maps in Go.

This example prints the updated prices in the terminal. However, Go also allows developers to manipulate and persist the data in many other ways, like sending it to a web API, writing it to a file, or rendering it in the user interface.

Add Key-Value Pairs to Maps

To add a new product and its price to a map, assign a value to a new key. For example, to add Starfield with a price of 74.99, enter:

gamePrices["Starfield"] = 74.99

Go checks if the key already exists. If it does not, it automatically adds the key-value pair to the map. The new product cannot be placed inside the original map literal as it has already been declared and initialized. Instead, the new item line needs to be placed after the original map declaration, within the same function.

This code example shows how to add a new key-value pair to an existing map:

package main

import "fmt"

func main() {
    // Original product prices
    gamePrices := map[string]float64{
        "Baldurs Gate 3":             69.99,
        "Cyberpunk 2077":             59.99,
        "Divinity: Original Sin II":  49.99,
        "The Witcher 3: Wild Hunt":   40.00,
    }

    // Add a new product dynamically after the declared map but before applying the discount
    gamePrices["Starfield"] = 74.99

    discountRate := 0.10 // 10% discount

    // Apply discount to all products, including the new one
    for name, price := range gamePrices {
        discountedPrice := price * (1 - discountRate)
        gamePrices[name] = discountedPrice
    }

    // Print updated prices
    fmt.Println("Discounted product prices:")
    for name, price := range gamePrices {
        fmt.Printf("- %s: $%.2f\n", name, price)
    }
}

The Starfield item is placed before the discount loop to ensure it's included in the same logic. If you place it after the discount loop, the discount is not applied.

Add new item to a Go map.

Use this option to update maps dynamically, for example, to add user-selected products to a shopping cart or update in-session data. This approach ensures that the same logic applies to all entries.

Note: Go maps do not maintain the order of key-value pairs. When you add a new pair, it is not placed at the end or the beginning of the list but stored according to Go's internal implementation.

Update an Existing Value

Assigning a new value to an existing key overwrites the original value. For example, to reduce the Cyberpunk 2077 price to 49.99, add the following line:

gamePrices["Cyberpunk 2077"] = 49.99

To lower the price during runtime, add the new line after the map is declared. To skip the 10% discount, add the line after the discount loop:

package main

import "fmt"

func main() {
    // Original product prices
    gamePrices := map[string]float64{
        "Baldurs Gate 3":             69.99,
        "Cyberpunk 2077":             59.99,
        "Divinity: Original Sin II":  49.99,
        "The Witcher 3: Wild Hunt":   40.00,
    }

    // Add a new product dynamically after the declared map but before applying the discount
    gamePrices["Starfield"] = 74.99

    discountRate := 0.10 // 10% discount

    // Apply discount to all products, including the new one
    for name, price := range gamePrices {
        discountedPrice := price * (1 - discountRate)
        gamePrices[name] = discountedPrice
    }

  // Override the original price for Cyberpunk 2077
     gamePrices["Cyberpunk 2077"] = 49.99

    // Print updated prices
    fmt.Println("Discounted product prices:")
    for name, price := range gamePrices {
        fmt.Printf("- %s: $%.2f\n", name, price)
    }
}

The Cyberpunk 2077 price is displayed without the 10% discount applied to the other games.

Updating an existing value in Go maps.

This pattern is useful for applying discounts manually, updating stock, or modifying prices in real time.

Retrieve a Value From a Map

To access a specific value without looping through the entire map, use square brackets [] with the key name. For example, to retrieve the price for Baldurs Gate 3, use:

price := gamePrices["Baldurs Gate 3"]
fmt.Println("Price of Baldurs Gate 3: $%.2f\n", price)

The following example defines a map, retrieves the value of a specific key, and prints it to the terminal:

package main

import "fmt"

func main() {
    gamePrices := map[string]float64{
        "Baldurs Gate 3":            69.99,
        "Cyberpunk 2077":            59.99,
        "Divinity: Original Sin II": 49.99,
        "The Witcher 3: Wild Hunt":  40.00,
    }

    price := gamePrices["Baldurs Gate 3"]
    fmt.Printf("Price of Baldurs Gate 3: $%.2f\n", price)
}

The terminal displays the formatted message along with the price for Baldurs Gate 3.

Retrieving values from Go maps.

Use this option when you already know the key and only need to check its value.

Check if a Key Exists in a Map

Trying to read a key that does not exist in a Go map returns a zero value for the value type. To avoid misinterpreting the result, use the comma-ok idiom to check if a key exists.

To check if the game Hades exists within the map and print its price if available, use the following code:

    price, exists := gamePrices["Hades"]
    if exists {
        fmt.Printf("\nPrice of Hades: $%.2f\n", price)
    } else {
        fmt.Println("\nHades is not in stock.")
}

This is a full code example that includes the check:

package main

import "fmt"

func main() {
    // Original product prices
    gamePrices := map[string]float64{
        "Baldurs Gate 3":             69.99,
        "Cyberpunk 2077":             59.99,
        "Divinity: Original Sin II":  49.99,
        "The Witcher 3: Wild Hunt":   40.00,
    }

    // Add Starfield to the map
    gamePrices["Starfield"] = 74.99

    discountRate := 0.10 // 10% discount

    // Apply discount to all products
    for name, price := range gamePrices {
        discountedPrice := price * (1 - discountRate)
        gamePrices[name] = discountedPrice
    }

    // Override the discounted price for Cyberpunk 2077
    gamePrices["Cyberpunk 2077"] = 49.99

    // Print updated prices
    fmt.Println("Discounted product prices:")
    for name, price := range gamePrices {
        fmt.Printf("- %s: $%.2f\n", name, price)
    }

    // Check if "Hades" is in stock
    price, exists := gamePrices["Hades"]
    if exists {
        fmt.Printf("\nPrice of Hades: $%.2f\n", price)
    } else {
        fmt.Println("\nHades is not in stock.")
    }
}

Since Hades is not part of the map, Go prints a message that indicates the item is not in stock.

Checking if an item exists in a Go map.

This is useful in scenarios when you need to check the inventory status, validate form input, or verify user sessions dynamically.

Delete a Key From a Map

The delete() function deletes the specified key and its value from the map. If the key does not exist, Go takes no action, and there is no error message.

Use the following line to remove The Witcher 3: Wild Hunt from the gamePrices map:

delete(gamePrices, "The Witcher 3: Wild Hunt")

Call delete() before other operations that rely on the map's content, such as printing, or the entry will still appear. For example:

package main

import "fmt"

func main() {
    // Original product prices
    gamePrices := map[string]float64{
        "Baldurs Gate 3":             69.99,
        "Cyberpunk 2077":             59.99,
        "Divinity: Original Sin II":  49.99,
        "The Witcher 3: Wild Hunt":   40.00,
    }

    // Add Starfield to the map
    gamePrices["Starfield"] = 74.99

    discountRate := 0.10 // 10% discount

    // Apply discount to all products
    for name, price := range gamePrices {
        discountedPrice := price * (1 - discountRate)
        gamePrices[name] = discountedPrice
    }

    // Override the discounted price for Cyberpunk 2077
    gamePrices["Cyberpunk 2077"] = 49.99

    // Delete The Witcher 3 before printing
    delete(gamePrices, "The Witcher 3: Wild Hunt")

    // Print updated prices
    fmt.Println("Discounted product prices:")
    for name, price := range gamePrices {
        fmt.Printf("- %s: $%.2f\n", name, price)
    }
}

The code removes The Witcher 3: Wild Hunt from the map before printing.

Deleting an item from the Go map.

This function is often used to remove discontinued items, expired session data, or user-selected options from a shopping cart.

Conclusion

The article showed how Go maps work and how to perform basic operations for managing key-pair values. Maps provide a fast and straightforward way to model relationships between non-persistent data, such as temporary product-price mappings or in-session user data.

For persistent and multiuser storage, use a dedicated database server such as MySQL, PostgreSQL, or Redis.

Was this article helpful?
YesNo