Go: 无效操作 - type *map[key]value 不支持索引
Go: invalid operation - type *map[key]value does not support indexing
我正在尝试编写一个函数来修改由指针传递的原始映射,但 Go 不允许这样做。假设我有一张大地图,不想来回复制它。
使用按值传递的代码正在运行并且正在做我需要的但涉及按值传递 (playground):
package main
import "fmt"
type Currency string
type Amount struct {
Currency Currency
Value float32
}
type Balance map[Currency]float32
func (b Balance) Add(amount Amount) Balance {
current, ok := b[amount.Currency]
if ok {
b[amount.Currency] = current + amount.Value
} else {
b[amount.Currency] = amount.Value
}
return b
}
func main() {
b := Balance{Currency("USD"): 100.0}
b = b.Add(Amount{Currency: Currency("USD"), Value: 5.0})
fmt.Println("Balance: ", b)
}
但是如果我尝试像这里一样将参数作为指针传递 (playground):
func (b *Balance) Add(amount Amount) *Balance {
current, ok := b[amount.Currency]
if ok {
b[amount.Currency] = current + amount.Value
} else {
b[amount.Currency] = amount.Value
}
return b
}
我遇到编译错误:
prog.go:15: invalid operation: b[amount.Currency] (type *Balance does not support indexing)
prog.go:17: invalid operation: b[amount.Currency] (type *Balance does not support indexing)
prog.go:19: invalid operation: b[amount.Currency] (type *Balance does not support indexing)
我该如何处理?
您可以简单地取消引用 b
:(*b)
https://play.golang.org/p/Xq6qFy4_PC
func (b *Balance) Add(amount Amount) *Balance {
current, ok := (*b)[amount.Currency]
if ok {
(*b)[amount.Currency] = current + amount.Value
} else {
(*b)[amount.Currency] = amount.Value
}
return b
}
更新
@Serdmanczyk 提出了一个很好的观点......您可以安全地按值传递地图,底层地图将被更新,而不是地图的副本。也就是说;在地图的情况下按值传递意味着传递地图的地址,而不是地图的内容。
见https://play.golang.org/p/i7Yz4zMq4v
type foo map[string]string
func main() {
a := foo{}
a["hello"] = "world"
fmt.Printf("%#v\n", a)
mod(a)
fmt.Printf("%#v\n", a)
}
func mod(f foo) {
f["hello"] = "cruel world"
}
输出:
main.foo{"hello":"world"}
main.foo{"hello":"cruel world"}
您正试图在指针而不是地图本身上建立索引。有点令人困惑,因为通常指针与值的解除引用对于结构来说是自动的。但是,如果您的结构只是一个映射,那么它只是通过引用传入,因此您不必担心创建作用于指针的方法以避免每次都复制整个结构。以下代码等效于您的第一个代码段,但使用指针类型。
package main
import "fmt"
type Currency string
type Amount struct {
Currency Currency
Value float32
}
type Balance map[Currency]float32
func (b *Balance) Add(amount Amount) *Balance {
current, ok := (*b)[amount.Currency]
if ok {
(*b)[amount.Currency] = current + amount.Value
} else {
(*b)[amount.Currency] = amount.Value
}
return b
}
func main() {
b := &Balance{Currency("USD"): 100.0}
b = b.Add(Amount{Currency: Currency("USD"), Value: 5.0})
fmt.Println("Balance: ", (*b))
}
但要回答如何处理它:如果你的结构只是 map 类型,我不会担心编写你的接收函数来获取指针,而只接收值,因为该值无论如何只是一个引用.在您的原始代码段中点赞。
我正在尝试编写一个函数来修改由指针传递的原始映射,但 Go 不允许这样做。假设我有一张大地图,不想来回复制它。
使用按值传递的代码正在运行并且正在做我需要的但涉及按值传递 (playground):
package main
import "fmt"
type Currency string
type Amount struct {
Currency Currency
Value float32
}
type Balance map[Currency]float32
func (b Balance) Add(amount Amount) Balance {
current, ok := b[amount.Currency]
if ok {
b[amount.Currency] = current + amount.Value
} else {
b[amount.Currency] = amount.Value
}
return b
}
func main() {
b := Balance{Currency("USD"): 100.0}
b = b.Add(Amount{Currency: Currency("USD"), Value: 5.0})
fmt.Println("Balance: ", b)
}
但是如果我尝试像这里一样将参数作为指针传递 (playground):
func (b *Balance) Add(amount Amount) *Balance {
current, ok := b[amount.Currency]
if ok {
b[amount.Currency] = current + amount.Value
} else {
b[amount.Currency] = amount.Value
}
return b
}
我遇到编译错误:
prog.go:15: invalid operation: b[amount.Currency] (type *Balance does not support indexing)
prog.go:17: invalid operation: b[amount.Currency] (type *Balance does not support indexing)
prog.go:19: invalid operation: b[amount.Currency] (type *Balance does not support indexing)
我该如何处理?
您可以简单地取消引用 b
:(*b)
https://play.golang.org/p/Xq6qFy4_PC
func (b *Balance) Add(amount Amount) *Balance {
current, ok := (*b)[amount.Currency]
if ok {
(*b)[amount.Currency] = current + amount.Value
} else {
(*b)[amount.Currency] = amount.Value
}
return b
}
更新
@Serdmanczyk 提出了一个很好的观点......您可以安全地按值传递地图,底层地图将被更新,而不是地图的副本。也就是说;在地图的情况下按值传递意味着传递地图的地址,而不是地图的内容。
见https://play.golang.org/p/i7Yz4zMq4v
type foo map[string]string
func main() {
a := foo{}
a["hello"] = "world"
fmt.Printf("%#v\n", a)
mod(a)
fmt.Printf("%#v\n", a)
}
func mod(f foo) {
f["hello"] = "cruel world"
}
输出:
main.foo{"hello":"world"}
main.foo{"hello":"cruel world"}
您正试图在指针而不是地图本身上建立索引。有点令人困惑,因为通常指针与值的解除引用对于结构来说是自动的。但是,如果您的结构只是一个映射,那么它只是通过引用传入,因此您不必担心创建作用于指针的方法以避免每次都复制整个结构。以下代码等效于您的第一个代码段,但使用指针类型。
package main
import "fmt"
type Currency string
type Amount struct {
Currency Currency
Value float32
}
type Balance map[Currency]float32
func (b *Balance) Add(amount Amount) *Balance {
current, ok := (*b)[amount.Currency]
if ok {
(*b)[amount.Currency] = current + amount.Value
} else {
(*b)[amount.Currency] = amount.Value
}
return b
}
func main() {
b := &Balance{Currency("USD"): 100.0}
b = b.Add(Amount{Currency: Currency("USD"), Value: 5.0})
fmt.Println("Balance: ", (*b))
}
但要回答如何处理它:如果你的结构只是 map 类型,我不会担心编写你的接收函数来获取指针,而只接收值,因为该值无论如何只是一个引用.在您的原始代码段中点赞。