用Go语言的reflect和interface进行重述

由于对golang的reflect和interface进行了各种试验,所以写下此备忘录。

反思

首先是关于 reflect 的,但我想要处理动态类型的那个部分。
不过,因为有一张反射表格,所以特别不需要解释了吧,我觉得实际写一下可能更容易理解。
Go 语言 reflect 反射表格。

界面

经常听到类似于方法列表的说法,但是在Golang中,可以简单地使用,而不需要像Java的接口那样写很多内容。这是一个常见的例子,就像这样。

package main

import (
    "fmt"
)

type Animal interface {
    Cry() string
}

type Dog struct{}

func (d *Dog) Cry() string {
    return "わん"
}

type Cat struct{}

func (c *Cat) Cry() string {
    return "にゃん"
}

func Sound(a Animal) {
    fmt.Println(a.Cry())
}

func main() {
    Sound(&Dog{})
    Sound(&Cat{})
}

个人对这段代码感觉有些不对劲,于是进行了一些调查,似乎可以使用mixin?类似trait?的方式来实现。

混合?特征?

使用golang实现类似于php trait的东西可能有些奇怪,但可以使用interface来实现。让我稍微修改上面的示例代码。

package main

import (
    "fmt"
)

type IAnimal interface {
    Cry() string
}

type Animal struct {
    IAnimal
}

type Dog struct{}

func (d *Dog) Cry() string {
    return "わん"
}

type Cat struct{}

func (c *Cat) Cry() string {
    return "にゃん"
}

func main() {
    dog := Animal{&Dog{}}
    fmt.Println(dog.Cry())

    cat := Animal{&Cat{}}
    fmt.Println(cat.Cry())
}

虽然没有对已经声明的Dog和Cat进行更改,但是现在增加了一个新的構造体Animal。它的内容基本上是直接将interface插入其中。
当然也可以给它起一个名字,但是这样一来在调用时就需要写出这个名字。

type Animal struct {
    inf IAnimal
}
func main() {
    dog := Animal{&Dog{}}
    fmt.Println(dog.inf.Cry())
}

运用reflect动态地…

我本打算这样做的,但最后的结果是必须明确地在某个地方写下类型才能使其正常工作。我想做的是根据存储在数据库中的值来生成实例并调用函数,但是…在将值存储到结构体中并使用reflect编写的部分还不错,但在最初的处理中使用了switch结果。

package main

import (
    "fmt"
    "reflect"
    "strconv"
)

type IContainer interface {
    MethodA() string
    MethodB(x, y int) int
}

type Driver struct {
    IContainer
}

type DriverType int

const (
    ADD = "ADD"
    MINUS = "MINUS"
)

func CreateDriver(driver string) IContainer {
    switch driver {
    case ADD:
        return &Add{}
    case MINUS:
        return &Minus{}
    }
    return nil
}

func New(driver string, args ...interface{}) *Driver {
    container := CreateDriver(driver)
    rt, rv := reflect.TypeOf(container).Elem(), reflect.ValueOf(container).Elem()
    for i, arg := range args {
        field := rt.Field(i)
        value := rv.FieldByName(field.Name)
        value.Set(reflect.ValueOf(arg))
    }

    return &Driver{container}
}

type Add struct {
    Value int
}

func (c *Add) MethodA() string {
    return strconv.Itoa(c.Value)
}
func (c *Add) MethodB(x, y int) int {
    return (x + y) + c.Value
}

type Minus struct {
    Value int
    Digit int
}

func (c *Minus) MethodA() string {
    return fmt.Sprintf("%d, %d", c.Value, c.Digit)
}
func (c *Minus) MethodB(x, y int) int {
    return c.Value - (x+y)*c.Digit
}

func main() {
    a := New("ADD", 193)
    fmt.Println(a.MethodA())
    fmt.Println(a.MethodB(9, 3))

    m := New("MINUS", 200, 3)
    fmt.Println(m.MethodA())
    fmt.Println(m.MethodB(3, 9))
}

去游乐场

虽然我写了很多东西,学到了很多东西,但我仍然感觉自己的理解还不够深入。如果有更好的写作方式,请务必告诉我。

bannerAds