Dereferencing a map index in Golang

golang map
golang map of pointers to structs
golang map documentation
golang multidimensional map
golang len map
remove from map golang
golang append maps
golang map as set

I'm learning Go currently and I made this simple and crude inventory program just to tinker with structs and methods to understand how they work. In the driver file I try to call a method from and item type from the items map of the Cashier type. My method have pointer reciever to use the structs directly instead of making copies. When I run the program I get this error .\driver.go:11: cannot call pointer method on f[0] .\driver.go:11: cannot take the address of f[0]

Inventory.go:

package inventory


type item struct{
    itemName string
    amount int
}

type Cashier struct{
    items map[int]item
    cash int
}

func (c *Cashier) Buy(itemNum int){
    item, pass := c.items[itemNum]

    if pass{
        if item.amount == 1{
            delete(c.items, itemNum)
        } else{
            item.amount--
            c.items[itemNum] = item 
        }
        c.cash++
    }
}


func (c *Cashier) AddItem(name string, amount int){
    if c.items == nil{
        c.items = make(map[int]item)
    }
    temp := item{name, amount}
    index := len(c.items)
    c.items[index] = temp
}

func (c *Cashier) GetItems() map[int]item{
    return c.items;
}

func (i *item) GetName() string{
    return i.itemName
}

func (i *item) GetAmount() int{
    return i.amount
}

Driver.go:

package main

import "fmt"
import "inventory"

func main() {
    x := inventory.Cashier{}
    x.AddItem("item1", 13)
    f := x.GetItems()

    fmt.Println(f[0].GetAmount())
}

The part of the code that really pertains to my problem is the GetAmount function in inventory.go and print statement in the driver.go


A map entry cannot be addressed (as its address might change during map growth/shrink), so you cannot call pointer receiver methods on them.

Detail here: https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/4_pabWnsMp0

pointers - Dereferencing a map index in Golang, A map entry cannot be addressed (as its address might change during map growth/shrink), so you cannot call pointer receiver methods on  Benchmark, map versus slice. A map accelerates lookups: it uses a special hash code to guide a search. Here we compare a map search to a slice search. Version 1: In this code we look up a value from a small string map—only 4 keys are in the map. We locate the index of the value "bird."


As Volker said in his answer - you can't get address of an item in the map. What you should do - is to store pointers to items in your map, instead of storing item values:

package main

import "fmt"

type item struct {
    itemName string
    amount   int
}

type Cashier struct {
    items map[int]*item
    cash  int
}

func (c *Cashier) Buy(itemNum int) {
    item, pass := c.items[itemNum]

    if pass {
        if item.amount == 1 {
            delete(c.items, itemNum)
        } else {
            item.amount--
        }
        c.cash++
    }
}

func (c *Cashier) AddItem(name string, amount int) {
    if c.items == nil {
        c.items = make(map[int]*item)
    }
    temp := &item{name, amount}
    index := len(c.items)
    c.items[index] = temp
}

func (c *Cashier) GetItems() map[int]*item {
    return c.items
}

func (i *item) GetName() string {
    return i.itemName
}

func (i *item) GetAmount() int {
    return i.amount
}

func main() {
    x := Cashier{}
    x.AddItem("item1", 13)
    f := x.GetItems()
    fmt.Println(f[0].GetAmount()) // 13
    x.Buy(0)
    f = x.GetItems()
    fmt.Println(f[0].GetAmount()) // 12
}

http://play.golang.org/p/HkIg668fjN

Dereferencing a map index in Golang - pointers - iOS, driver.go:11: cannot take the address of f[0] Inventory.go: package inventory type item struct{ itemName string amount int } type Cashier struct{ items map[int]item  Pointers reference a location in memory where a value is stored rather than the value itself. (They point to something else) By using a pointer (*int) the zero function is able to modify the original variable. The * and & operators. In Go a pointer is represented using the * (asterisk) character followed by the type of the stored value.


While the other answers are useful, I think in this case it is best just to make non-mutating functions not take a pointer:

func (i item) GetName() string{
    return i.itemName
}

func (i item) GetAmount() int{
    return i.amount
}

spec: can take the address of map[x] · Issue #11865 · golang/go , current golang cannot can take the address of map[x]. like this m := map[int]int{} v:​= &m[1] // it will compile error But sometimes this is useful  Go maps in action. Andrew Gerrand 6 February 2013 Introduction. One of the most useful data structures in computer science is the hash table. Many hash table implementations exist with varying properties, but in general they offer fast lookups, adds, and deletes. Go provides a built-in map type that implements a hash table.


Solving the "does not support indexing" error in a Go program, So what you're telling the compiler to do is, get the first element in the slice, or the map item with key 0, and dereference that pointer. 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 Where keyType is the data type of map keys


If a map isn't a reference variable, what is it?, In my previous post I showed that Go maps are not reference variables, and are than a pointer shaped value which cannot be dereferenced. Dereferencing a pointer. Dereferencing a pointer means accessing the value of the variable which the pointer points to. *a is the syntax to deference a. Lets see how this works in a program. package main import ( "fmt" ) func main() { b := 255 a := &b fmt.Println("address of b is", a) fmt.Println("value of b is", *a) }


Programming in Go: Creating Applications for the 21st Century, The function's first statement uses an explicit dereference just to show what is Certain types in Go are reference types: maps, slices, channels, functions, and Array items are indexed using the [] index operator by their 0-based position,  The uninitialized pointer p in the main function is nil, and you can’t follow the nil pointer. If x is nil, an attempt to evaluate *x will cause a run-time panic. The Go Programming Language Specification: Address operators