使用接口时操纵struct字段

时间:2017-07-22 17:15:33

标签: pointers go struct interface

标题可能会产生误导,但要点......

我有一个界面Expression

type Expression interface {
    String() // skiped in implementation below
}

接口由多个结构实现,其中一些结构实现与字段值相同的接口:

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() {} // do nothing

结果代码不起作用(play):

  

main.go:29:不可能的类型切换案例:a.value(类型Expression)不能有动态类型UnaryExpression(缺少简化方法)

     

main.go:30:不可能的类型断言:

UnaryExpression does not implement Expression (Simplify method has pointer receiver)
     

main.go:59:不能在字段值中使用UnaryExpression文字(类型为UnaryExpression)作为表达式:

UnaryExpression does not implement Expression (Simplify method has pointer receiver)
     

main.go:60:不能使用UnaryExpression文字(类型为UnaryExpression)作为字段值中的表达式类型:

UnaryExpression does not implement Expression (Simplify method has pointer receiver)

我找到了this answer,看起来很相似,但我不知道如何应用它。

1 个答案:

答案 0 :(得分:4)

这里的关键是你在Simplify()的{​​{1}}定义中使用指针接收器:

UnaryExpression

您正在实施的其他方法不使用指针接收器:

func (a *UnaryExpression) Simplify()

通常,在Go中,最佳做法是让同一类型的所有方法使用相同类型的接收器(即,如果一个方法使用指针接收器,则它们都应该。同样,如果一个方法使用非指针接收器,它们都应该用于特定类型)。

在这种情况下,如果从// One example func (a IdentExpression) Simplify() {} Simplify方法移除指针接收器,代码将编译。希望这有帮助!

修改:Here is a more comprehensive answer that explains exactly why this error happens, it's really a good read.