假设我有这个界面
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
。
无论如何,我认为人们已经尝试过类似的东西并提出了更优雅的解决方案,所以我想听听一些想法。
答案 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优雅是可读的,可维护的和准确的 - 而不是官僚主义,并试图保护你自己。