golang反模式中的基本API?

时间:2015-06-27 22:04:13

标签: api design-patterns go

如果我错了,请纠正我,但是因为我不知道API是允许我通过接口修改和请求数据的东西,这是我想要在golang中做的事情。例如,我有一个用户界面:

interface IUser {
  GetId() int
  GetName() string
  GetSignupDate() time
  GetPermissions() []IPermission
  Delete()
}

这对我来说就像活动记录一样,如果我想创建一个具有新id的新用户,我将不得不使用new,因为go并不支持静态函数,据我所知,这意味着我会我的界面中还需要一个提交功能,这对我来说更糟糕,我在这里做错了什么?

2 个答案:

答案 0 :(得分:2)

在Go中,接口是行为的。也就是说,他们比 更能描述 的内容。您的示例看起来像是在尝试在Go中编写C#,在接口类之前大量使用I。但是,仅由一种类型实现的接口有点浪费时间。

相反,请考虑:

interface Deleteable {  // You'd probably be tempted to call this IDeleteable
                        // Effective go suggests Deleter, but the grammar 
                        // sounds weird
    Delete() err
}

现在您可以创建一个执行批量删除的功能:

func BatchDelete(victims []Deleteable) {
    // Do some cool things for batching, connect to db, start a transaction
    for _, victim := range(victims) {
        victim.Delete()  // Or arrange for this function to be called somehow.
    }
}

通过为Update,Serialize等创建接口,以及在实现这些方法的具体结构中存储您的实际用户/权限/等,您可能会更快地开始。 (注意在Go中你不必说一个类型实现一个接口,它会自动发生"自动")。您也不必为每个方法(Updater,Serializable)提供单一界面,但您可以将它们全部捆绑到一个界面中:

type DBObject interface {
    Update()
    Serialize() RowType
    Delete()
}

type User struct {
    Id int
    Name string
    // ... etc
}

请记住,您的模型始终可以"填写"要从API返回的User对象,即使User对象的实际表示更加分散,例如RDF三倍。

答案 1 :(得分:0)

我同意@ZanLynx的评论。 Go的标准库似乎更喜欢API的接口方式。

package main

import "fmt"

type S string
type I interface{ M() S }
func (s S) M() S { return s }
func API(i I)            I { return i.M() }

func main() {
  s := S("interface way")
  fmt.Println(API(s))
}

值得注意的是,采用一种方法接口的API可以重写为采用函数类型。

package main

import "fmt"

func API(f func() string) string { return f() }

func main() {
  f := func() string { return "higher-order way" }
  fmt.Println(API(f))
}

作为API的作者,可以提供两种机制,并让API使用者确定调用的样式。参见http://aquaraga.github.io/functional-programming/golang/2016/11/19/golang-interfaces-vs-functions.html