在Golang中解引用地图索引。

huangapple go评论193阅读模式
英文:

Dereferencing a map index in Golang

问题

我正在学习Go语言,目前我制作了这个简单而粗糙的库存程序,只是为了玩弄结构体和方法,以理解它们的工作原理。在驱动文件中,我尝试从Cashier类型的items映射中调用item类型的方法。我的方法使用指针接收器直接使用结构体,而不是创建副本。当我运行程序时,我得到了这个错误.\driver.go:11: cannot call pointer method on f[0] .\driver.go:11: cannot take the address of f[0]

Inventory.go:

  1. package inventory
  2. type item struct{
  3. itemName string
  4. amount int
  5. }
  6. type Cashier struct{
  7. items map[int]item
  8. cash int
  9. }
  10. func (c *Cashier) Buy(itemNum int){
  11. item, pass := c.items[itemNum]
  12. if pass{
  13. if item.amount == 1{
  14. delete(c.items, itemNum)
  15. } else{
  16. item.amount--
  17. c.items[itemNum] = item
  18. }
  19. c.cash++
  20. }
  21. }
  22. func (c *Cashier) AddItem(name string, amount int){
  23. if c.items == nil{
  24. c.items = make(map[int]item)
  25. }
  26. temp := item{name, amount}
  27. index := len(c.items)
  28. c.items[index] = temp
  29. }
  30. func (c *Cashier) GetItems() map[int]item{
  31. return c.items;
  32. }
  33. func (i *item) GetName() string{
  34. return i.itemName
  35. }
  36. func (i *item) GetAmount() int{
  37. return i.amount
  38. }

Driver.go:

  1. package main
  2. import "fmt"
  3. import "inventory"
  4. func main() {
  5. x := inventory.Cashier{}
  6. x.AddItem("item1", 13)
  7. f := x.GetItems()
  8. fmt.Println(f[0].GetAmount())
  9. }

与我的问题相关的代码部分是inventory.go中的GetAmount函数和driver.go中的打印语句。

英文:

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:

  1. package inventory
  2. type item struct{
  3. itemName string
  4. amount int
  5. }
  6. type Cashier struct{
  7. items map[int]item
  8. cash int
  9. }
  10. func (c *Cashier) Buy(itemNum int){
  11. item, pass := c.items[itemNum]
  12. if pass{
  13. if item.amount == 1{
  14. delete(c.items, itemNum)
  15. } else{
  16. item.amount--
  17. c.items[itemNum] = item
  18. }
  19. c.cash++
  20. }
  21. }
  22. func (c *Cashier) AddItem(name string, amount int){
  23. if c.items == nil{
  24. c.items = make(map[int]item)
  25. }
  26. temp := item{name, amount}
  27. index := len(c.items)
  28. c.items[index] = temp
  29. }
  30. func (c *Cashier) GetItems() map[int]item{
  31. return c.items;
  32. }
  33. func (i *item) GetName() string{
  34. return i.itemName
  35. }
  36. func (i *item) GetAmount() int{
  37. return i.amount
  38. }

Driver.go:

  1. package main
  2. import "fmt"
  3. import "inventory"
  4. func main() {
  5. x := inventory.Cashier{}
  6. x.AddItem("item1", 13)
  7. f := x.GetItems()
  8. fmt.Println(f[0].GetAmount())
  9. }

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

得分: 23

地图条目无法被寻址(因为在地图的增长/缩小过程中,它们的地址可能会发生变化),因此无法在它们上面调用指针接收器方法。

详细信息请参阅:https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/4_pabWnsMp0

英文:

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

得分: 20

如Volker在他的回答中所说,你不能获取映射中项目的地址。你应该存储指向映射中项目的指针,而不是存储项目的值:

  1. package main
  2. import "fmt"
  3. type item struct {
  4. itemName string
  5. amount int
  6. }
  7. type Cashier struct {
  8. items map[int]*item
  9. cash int
  10. }
  11. func (c *Cashier) Buy(itemNum int) {
  12. item, pass := c.items[itemNum]
  13. if pass {
  14. if item.amount == 1 {
  15. delete(c.items, itemNum)
  16. } else {
  17. item.amount--
  18. }
  19. c.cash++
  20. }
  21. }
  22. func (c *Cashier) AddItem(name string, amount int) {
  23. if c.items == nil {
  24. c.items = make(map[int]*item)
  25. }
  26. temp := &item{name, amount}
  27. index := len(c.items)
  28. c.items[index] = temp
  29. }
  30. func (c *Cashier) GetItems() map[int]*item {
  31. return c.items
  32. }
  33. func (i *item) GetName() string {
  34. return i.itemName
  35. }
  36. func (i *item) GetAmount() int {
  37. return i.amount
  38. }
  39. func main() {
  40. x := Cashier{}
  41. x.AddItem("item1", 13)
  42. f := x.GetItems()
  43. fmt.Println(f[0].GetAmount()) // 13
  44. x.Buy(0)
  45. f = x.GetItems()
  46. fmt.Println(f[0].GetAmount()) // 12
  47. }

你可以在这里运行代码:http://play.golang.org/p/HkIg668fjN

英文:

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:

  1. package main
  2. import "fmt"
  3. type item struct {
  4. itemName string
  5. amount int
  6. }
  7. type Cashier struct {
  8. items map[int]*item
  9. cash int
  10. }
  11. func (c *Cashier) Buy(itemNum int) {
  12. item, pass := c.items[itemNum]
  13. if pass {
  14. if item.amount == 1 {
  15. delete(c.items, itemNum)
  16. } else {
  17. item.amount--
  18. }
  19. c.cash++
  20. }
  21. }
  22. func (c *Cashier) AddItem(name string, amount int) {
  23. if c.items == nil {
  24. c.items = make(map[int]*item)
  25. }
  26. temp := &item{name, amount}
  27. index := len(c.items)
  28. c.items[index] = temp
  29. }
  30. func (c *Cashier) GetItems() map[int]*item {
  31. return c.items
  32. }
  33. func (i *item) GetName() string {
  34. return i.itemName
  35. }
  36. func (i *item) GetAmount() int {
  37. return i.amount
  38. }
  39. func main() {
  40. x := Cashier{}
  41. x.AddItem("item1", 13)
  42. f := x.GetItems()
  43. fmt.Println(f[0].GetAmount()) // 13
  44. x.Buy(0)
  45. f = x.GetItems()
  46. fmt.Println(f[0].GetAmount()) // 12
  47. }

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

答案3

得分: 3

虽然其他答案很有用,但我认为在这种情况下最好的做法是使非变异函数接受指针:

  1. func (i item) GetName() string{
  2. return i.itemName
  3. }
  4. func (i item) GetAmount() int{
  5. return i.amount
  6. }
英文:

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

  1. func (i item) GetName() string{
  2. return i.itemName
  3. }
  4. func (i item) GetAmount() int{
  5. return i.amount
  6. }

huangapple
  • 本文由 发表于 2013年11月27日 01:55:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/20224478.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定