覆盖接口指针值

时间:2017-07-20 20:24:52

标签: pointers go struct interface

我创建了一个界面,用于使用struct值进行基本数学运算。接口的数学函数总是更新结构指针的值。

我的问题是,在某些时候,我想将值覆盖到初始值,但我只有接口可以使用。因为它是一个指针界面(不是100%肯定,如果这是人们所说的),我无法克隆"结构的初始值,以便稍后覆盖。

请注意我尽量避免反思。

这是我的代码。可能比我试图解释它更有意义:

package main

import (
    "fmt"
)

type mather interface {
    add(mather) mather
    sub(mather) mather
}

type float struct {
    value float64
}

func (f *float) add(m mather) mather {
    f.value += m.(*float).value
    return f
}

func (f *float) sub(m mather) mather {
    f.value -= m.(*float).value
    return f
}

func (f *float) get() interface{} {
    return *f
}

func main() {
    var a, b, c mather

    a = &float{2} // this could be any time. approximitly 10 possible types
    b = &float{7} // this could be any time. approximitly 10 possible types

    // float can't be used again below, only mather

    c = a

    fmt.Println(a)
    fmt.Println(b)
    fmt.Println()

    // a's math
    doMath(a)

    // now math is done, we need to reset the value from before the math was done
    // set *a equal to *c. (a == &float{2})
    resetMath(a, c)

    // b's math
    doMath(b)

    // now math is done, we need to reset the value from before the math was done
    // set *b equal to *c. (b == &float{7})
    resetMath(b, c)

    fmt.Println(a)
    fmt.Println(b)

}

func doMath(m mather) {
    m.add(&float{3})
}

func resetMath(m mather, r mather) {
    m = r
}

https://play.golang.org/p/3Szk8uQGy5

2 个答案:

答案 0 :(得分:2)

您需要在clone界面中定义setmather方法,即:

type mather interface {
    add(mather) mather
    sub(mather) mather
    get() interface{}
    clone() mather
    set(v mather)
}

get类型中setclonefloat的实现如下:

func (f *float) get() interface{} {
    return f.value
}

func (f *float) clone() mather {
    return &float{f.value}
}

func (f *float) set(v mather) {
    switch v := v.(type) {
    case *float:
        f.value = v.value
    //handle other possible types...
    default:
        //handle unknown types
    }
}

working example in Playground。唯一复杂的部分是set,您应该在其中确定基础类型。在这里,您可以使用type switch获取基础类型,然后将其分配给float。需要在其他基础类型中添加类似的代码(您提到有10种可能的类型)。

答案 1 :(得分:1)

你可以使用简单的寻址操作符来实现它,如果你有一个基础类型的引用,你可以通过类型断言获得它,而不必诉诸于反射。获得*float后,很容易:

f := &float{2}

var a, b *float
a = f
b = new(float)
*b = *f        // Assign the value pointed to by f to the value pointed to by b

在这种情况下,您的本地变量现在是*float而不是mather,但至少在您的示例中无关紧要。如果它确实重要,如上所述,您可以使用类型断言。