在Go语言中创建结构体的原型。

huangapple go评论75阅读模式
英文:

Prototyping struct in Go

问题

我的用例是,我需要在Go中有几个结构体,它们将具有相同签名的方法,并且不一定必须具有所有方法。以下代码描述了要求,并表示了我的当前解决方案。

type calc struct {
    fn    func(a, b int) int
    gn    func(a string) bool
    name  string
}

func add(a, b int) int {
    return a + b
}

func bar(foo string) bool {
    // do something
}

func sub(a, b int) int {
    return a - b
}

func main() {
    for c := range []calc{
        {
            fn:   add,
            gn:   bar,
            name: "addition",
        },
        {
            fn:   sub,
            name: "subtraction",
        },
    } {
        fmt.Printf("%s(10, 15) returned: %d\n", c.name, c.fn(10, 15))
        if c.gn != nil {
            c.gn(c.name)
        }
    }
}

我的问题是如何改进这段代码?在Go中实现这个有什么最佳方式?我能否使用接口实现更好的解决方案?

英文:

My use case is, I need to have several structs in Go, who will have methods of same signatures and not necessarily have to have all the methods. The following code describes the requirements and also represents my current solution.

type calc struct {
    fn func(a, b int) int
    gn func(a string) bool
    name string
}

func add(a, b int) int {
    return a + b
}

func bar(foo string) bool {
    // do something
}

func sub(a, b int) int {
    return a - b
}

func main() {
    for c := range []calc{{
        fn: add,
        gn: bar,
        name: "addition",
    }, {
        fn: sub,
        name: "subtraction",
    }} {
        fmt.Printf("%s(10, 15) returned: %d\n", c.name, c.fn(10, 15))
        if c.gn != nil {
            c.gn(c.name)
        }
    }
}

My question is how to improve this code? What's the best way to achieve this in Go? Can I achieve a better solution using interface?

答案1

得分: 4

使用接口。

type Op interface {
    Name() string
    Do(a, b int) int
}

type Add struct{}

func (Add) Name() string    { return "add" }
func (Add) Do(a, b int) int { return a + b }

type Sub struct{}

func (Sub) Name() string    { return "sub" }
func (Sub) Do(a, b int) int { return a - b }

Playground: http://play.golang.org/p/LjJt6D0hNF.

编辑: 由于您编辑了您的问题,这里是一个示例,说明如何将接口断言为更广泛的接口以完成您的任务:

type RevOp interface {
    Op
    ReverseDo(a, b int) int
}

// ...

func (Add) ReverseDo(a, b int) int { return a - b }

// ...

fmt.Printf("%s(10, 15) 返回: %d\n", op.Name(), op.Do(10, 15))
if op, ok := op.(RevOp); ok {
    fmt.Printf("反转 %s(10, 15) 返回: %d\n", op.Name(), op.ReverseDo(10, 15))
}

Playground: http://play.golang.org/p/MQ6LlPDcEi.

英文:

Use interfaces.

type Op interface {
	Name() string
	Do(a, b int) int
}

type Add struct{}

func (Add) Name() string    { return "add" }
func (Add) Do(a, b int) int { return a + b }

type Sub struct{}

func (Sub) Name() string    { return "sub" }
func (Sub) Do(a, b int) int { return a - b }

Playground: http://play.golang.org/p/LjJt6D0hNF.


EDIT: Since you've edited your question, here is an example of how you could use asserting and interface to a broader interface for your task:

type RevOp interface {
	Op
	ReverseDo(a, b int) int
}

// ...

func (Add) ReverseDo(a, b int) int { return a - b }

// ...

fmt.Printf("%s(10, 15) returned: %d\n", op.Name(), op.Do(10, 15))
if op, ok := op.(RevOp); ok {
	fmt.Printf("reverse of %s(10, 15) returned: %d\n", op.Name(), op.ReverseDo(10, 15))
}

Playground: http://play.golang.org/p/MQ6LlPDcEi.

答案2

得分: 0

我已经与一些人面对面讨论过,显然我的解决方案是正确的。虽然可以使用接口进行重写,但这并不一定是一种改进。

英文:

I've discussed with some people in person and apparently my solution was correct. While it can be rewritten using interface, that's not necessarily an improvement.

huangapple
  • 本文由 发表于 2015年9月1日 22:16:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/32333981.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定