Dereferencing a map index in Golang

匿名 (未验证) 提交于 2019-12-03 01:57:01

问题:

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

回答1:

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



回答2:

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



回答3:

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 } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!