从界面创建处理程序

时间:2016-01-12 06:42:53

标签: go

假设我有这个界面

chisq.test(color.blind,correct=F)

Pearson's Chi-squared test

data:  color.blind
X-squared = 27.139, df = 1, p-value = 1.894e-07

我想制作处理程序,它几乎只是在调用type Selecter interface { Select(vars ...string) error } 函数后返回该接口的JSON形式。像这样:

Select

因此,如果func MakeHandler(s Selecter) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { //... do some stuff to get vars ... if err := s.Select(v1, v2); err != nil { //... blah blah errors ... } b, err := json.Marshal(s) if err != nil { //... blah blah errors ... } w.Write(b) } } CoolType我可以做这样的事情

Selecter

我遇到的根本问题是type CoolType struct { CoolString string `json:"cool_string"` CoolInt int `json:"cool_int"` CoolBool bool `json:"cool_bool"` } func (c *CoolType) Select(vars ...string) error { // fill up c using vars return nil } // this looks kinda ugly to me too fn := MakeHandler(CoolType{}) 是一个接口并使用指针。由于s可以在对s的调用和对Select的调用之间进行修改,因此这会使goroutine中的安全性变得不安全。

我真的认为这是我想要实现这个的方式,因为它对我来说变得相当简洁和容易,但我想我错过了一些东西。我可以使用Marshal或更改reflect界面让Selecter返回Select,因为我并不特别关心类型是什么。然后,我想在interface{}的每个实现中制作一个新类型的副本。或者互斥锁可以工作。或者更好的方法是让我的所有Select类型实现Selecter并成为ServeHTTP

无论如何,我认为人们已经尝试过类似的东西并提出了更优雅的解决方案,所以我想听听一些想法。

1 个答案:

答案 0 :(得分:1)

如果你害怕突变传递一个值的副本。要做到这一点,您可能需要将界面更改为:

type Selecter interface {
    Select(vars ...string) (Selecter, error)
}

并更改Select方法以使值接收器完成接口。它将是func (c CoolType) Select(vars ...string) (CoolType, error)

然后将s作为值而不是指针传递,并调用Select:

if s, err := s.Select(v1, v2); err != nil {
     //... blah blah errors ...
}

您可以争辩说您丢失了有关该类型的信息,但在将该值作为Selecter界面传递时您已经丢失了该信息。

但总的来说你的实施很好。我的感觉是,Go优雅与其他语言不同。我说Go优雅是可读的,可维护的和准确的 - 而不是官僚主义,并试图保护你自己。