英文:
Manipulate struct field when using interface
问题
标题可能有些误导,但要点是...
我有一个单一的接口Expression
:
type Expression interface {
String() // 在下面的实现中被省略
}
该接口由多个结构体实现,其中一些结构体将同一个接口作为字段值实现:
type IdentExpression struct {
value string
}
type UnaryExpression struct {
token string
value Expression
}
func (a *UnaryExpression) Simplify() {
var finalValue Expression
switch a.value.(type) {
case UnaryExpression:
tmp := a.value.(UnaryExpression)
switch tmp.value.(type) {
case UnaryExpression:
tmp = tmp.value.(UnaryExpression)
finalValue = tmp.value
}
}
a.value = finalValue
}
给定表达式-(-(-(1)))
,UnaryExpression.Simplify()
将简化表达式为-(1)
。 (play)
我想用Simplify()
方法扩展该接口:
type Expression interface {
Simplify()
String() string
}
// ...
func (a IdentExpression) Simplify() {} // 什么也不做
结果代码无法工作 (play):
> main.go:29: impossible type switch case: a.value (type Expression) cannot have dynamic type UnaryExpression (missing Simplify method)
>
> main.go:30: impossible type assertion:
>
> UnaryExpression does not implement Expression (Simplify method has pointer receiver)
> main.go:59: cannot use UnaryExpression literal (type UnaryExpression) as type Expression in field value:
>
> UnaryExpression does not implement Expression (Simplify method has pointer receiver)
>
> main.go:60: cannot use UnaryExpression literal (type UnaryExpression) as type Expression in field value:
>
> UnaryExpression does not implement Expression (Simplify method has pointer receiver)
我找到了这个答案,看起来很相似,但我不知道如何在我的情况下应用它。
英文:
The title might be misleading, but to the point...
I have a single interface Expression
:
type Expression interface {
String() // skiped in implementation below
}
The interface is implemented by multiple structs, some of which implements same interface as a field value:
type IdentExpression struct {
value string
}
type UnaryExpression struct {
token string
value Expression
}
func (a *UnaryExpression) Simplify() {
var finalValue Expression
switch a.value.(type) {
case UnaryExpression:
tmp := a.value.(UnaryExpression)
switch tmp.value.(type) {
case UnaryExpression:
tmp = tmp.value.(UnaryExpression)
finalValue = tmp.value
}
}
a.value = finalValue
}
Given expression -(-(-(1)))
, UnaryExpression.Simplify()
will simplify the expression to -(1)
. (play)
I would like to extend the interface with Simplify()
method:
type Expression interface {
Simplify()
String() string
}
// ...
func (a IdentExpression) Simplify() {} // do nothing
Resulting code does not work (play):
> main.go:29: impossible type switch case: a.value (type Expression) cannot have dynamic type UnaryExpression (missing Simplify method)
>
> main.go:30: impossible type assertion:
>
> UnaryExpression does not implement Expression (Simplify method has pointer receiver)
> main.go:59: cannot use UnaryExpression literal (type UnaryExpression) as type Expression in field value:
>
> UnaryExpression does not implement Expression (Simplify method has pointer receiver)
>
> main.go:60: cannot use UnaryExpression literal (type UnaryExpression) as type Expression in field value:
>
> UnaryExpression does not implement Expression (Simplify method has pointer receiver)
I have found this answer, which looks similar however I do not know how to apply it in my case.
答案1
得分: 4
这里的关键是,在你对UnaryExpression
的Simplify()
方法的定义中,你使用了指针接收器:
func (a *UnaryExpression) Simplify()
而你实现的其他方法没有使用指针接收器:
// 一个例子
func (a IdentExpression) Simplify() {}
通常,在Go语言中,最佳实践是让同一类型的所有方法都使用相同类型的接收器(即,如果一个方法使用了指针接收器,那么所有方法都应该使用指针接收器;同样地,如果一个方法使用了非指针接收器,那么所有方法都应该使用非指针接收器)。
在这种情况下,如果你从UnaryExpression
的Simplify
方法中移除指针接收器,代码将能够编译通过。希望对你有帮助!
编辑:这里有一个更详细的答案,解释了为什么会出现这个错误,非常值得一读。
英文:
The key here is that you are using a pointer receiver in your definition of Simplify()
with respect to UnaryExpression
:
func (a *UnaryExpression) Simplify()
The other methods you are implementing don't use a pointer receiver:
// One example
func (a IdentExpression) Simplify() {}
Typically, in Go, it is considered best practice to have all methods on the same type use the same type of receiver (i.e. if one method uses a pointer receiver, they all should. Likewise, if one method uses a non-pointer receiver, they all should for that particular type).
In this case, the code will compile if you remove the pointer receiver from the Simplify
method of UnaryExpression
. Hope this helps!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论