我最近在我的代碼中找到了一個錯誤,我很困惑為什么 Go 沒有保護我免受它的影響。代碼大致是這樣的(下面是MCVE):
// common interface for events
interface Event ...
// concrete event type
type ConcreteEvent ...
func EventHandler(e Event) {
// check if the event has a specific type and treat that differently
c, ok := e.(ConcreteEvent)
if ok {
...
} else {
...
}
}
ce := ConcreteEvent{...}
// two calls to the event handler that are both accepted by Go
EventHandler(ce)
EventHandler(&ce)
奇怪的第一件事是兩個呼叫都被接受。好吧,就我而言,意思是毫無疑問的,所以為什么不接受兩者。但是,這是我主要關心的問題,第二個不會進入if內部的分支,EventHandler()而是進入else分支。如果我將檢查更改為c, ok := e.(*ConcreteEvent).
我的直覺是,這是 Go 設計中的一個小故障或錯誤。然而,改變它會改變現有代碼的行為,這使得在版本 1 中修復變得困難或不可能。然而,這不是我的主要關注點,而是找到這些情況并避免這個錯誤。那么,是否有任何方法(或編碼策略)可以避免這種情況或至少意識到這一點?
MCVE
代碼
package main
import "fmt"
// common interface for events
type Event interface {
Value() int
}
// concrete event type
type ConcreteEvent struct {
val int
}
func (e ConcreteEvent) Value() int {
return e.val
}
func EventHandler(e Event) {
// check if the event has a specific type and treat that differently
_, ok := e.(ConcreteEvent)
if ok {
fmt.Println("ConcreteEvent")
} else {
fmt.Println("general Event")
}
}
func main() {
ce := ConcreteEvent{
val: 42,
}
// two calls to the event handler that are both accepted by Go
EventHandler(ce)
EventHandler(&ce)
}
輸出
ConcreteEvent
general Event
uj5u.com熱心網友回復:
指標型別的方法集*T包括在值接收器上宣告的方法:
規格、方法集
對應指標型別*T的方法集是所有用接收者*T或T宣告的方法的集合(也就是還包含T的方法集)
因此,無論ConcreteEvent和*ConcreteEvent實作Event介面。
這不是語言中的“錯誤”。事實上,它已被正確記錄。為避免此問題,您可以:
使用指標接收器宣告方法,以便只有指標型別才能實作介面
或者如果這兩種型別始終有效,您可以使用雙重大小寫進行型別切換:
switch t := e.(type) {
case ConcreteEvent, *ConcreteEvent:
fmt.Println("ConcreteEvent", t.Value())
}
請注意,在 double 情況下,的型別t為Event。
uj5u.com熱心網友回復:
那么,是否有任何方法(或編碼策略)可以避免這種情況或至少意識到這一點?
不,這不是問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/369735.html
標籤:走
上一篇:為什么用|傳遞多個值作為Golang函式的引數作業?[復制]
下一篇:RabbitMQ發布后關閉連接
