英文:
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:
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())
}
与我的问题相关的代码部分是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:
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
得分: 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在他的回答中所说,你不能获取映射中项目的地址。你应该存储指向映射中项目的指针,而不是存储项目的值:
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
英文:
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
}
答案3
得分: 3
虽然其他答案很有用,但我认为在这种情况下最好的做法是使非变异函数不接受指针:
func (i item) GetName() string{
return i.itemName
}
func (i item) GetAmount() int{
return i.amount
}
英文:
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论