我想在gorilla/mux
路由和路由器类型上添加一个便利的util方法:
package util
import(
"net/http"
"github.com/0xor1/gorillaseed/src/server/lib/mux"
)
func (r *mux.Route) Subroute(tpl string, h http.Handler) *mux.Route{
return r.PathPrefix("/" + tpl).Subrouter().PathPrefix("/").Handler(h)
}
func (r *mux.Router) Subroute(tpl string, h http.Handler) *mux.Route{
return r.PathPrefix("/" + tpl).Subrouter().PathPrefix("/").Handler(h)
}
但编译器通知我
无法在非本地类型mux.Router
上定义新方法
那我怎么做到这一点?我是否创建了一个具有匿名mux.Route和mux.Router字段的新结构类型?或其他什么?
答案 0 :(得分:127)
正如编译器所提到的,您无法在另一个包中扩展现有类型。您可以按如下方式定义自己的别名或子包:
type MyRouter mux.Router
func (m *MyRouter) F() { ... }
或嵌入原始路由器:
type MyRouter struct {
*mux.Router
}
func (m *MyRouter) F() { ... }
...
r := &MyRouter{router}
r.F()
答案 1 :(得分:85)
我想扩展@jimt here给出的答案。这个答案是正确的,并帮助我彻底解决了这个问题。但是,对于我遇到麻烦的两种方法(别名,嵌入)都有一些警告。
note :我使用的是父母和孩子这两个词,虽然我不确定这是最适合作文的。基本上,parent是您要在本地修改的类型。 Child是尝试实现该修改的新类型。
type child parent
// or
type MyThing imported.Thing
type child struct {
parent
}
// or with import and pointer
type MyThing struct {
*imported.Thing
}
您可以在以下代码中看到这一点。
working example on the playground
package main
import (
"fmt"
)
type parent struct {
attr string
}
type childAlias parent
type childObjParent struct {
parent
}
type childPointerParent struct {
*parent
}
func (p *parent) parentDo(s string) { fmt.Println(s) }
func (c *childAlias) childAliasDo(s string) { fmt.Println(s) }
func (c *childObjParent) childObjParentDo(s string) { fmt.Println(s) }
func (c *childPointerParent) childPointerParentDo(s string) { fmt.Println(s) }
func main() {
p := &parent{"pAttr"}
c1 := &childAlias{"cAliasAttr"}
c2 := &childObjParent{}
// When the parent is a pointer it must be initialized.
// Otherwise, we get a nil pointer error when trying to set the attr.
c3 := &childPointerParent{}
c4 := &childPointerParent{&parent{}}
c2.attr = "cObjParentAttr"
// c3.attr = "cPointerParentAttr" // NOGO nil pointer dereference
c4.attr = "cPointerParentAttr"
// CAN do because we inherit parent's fields
fmt.Println(p.attr)
fmt.Println(c1.attr)
fmt.Println(c2.attr)
fmt.Println(c4.attr)
p.parentDo("called parentDo on parent")
c1.childAliasDo("called childAliasDo on ChildAlias")
c2.childObjParentDo("called childObjParentDo on ChildObjParent")
c3.childPointerParentDo("called childPointerParentDo on ChildPointerParent")
c4.childPointerParentDo("called childPointerParentDo on ChildPointerParent")
// CANNOT do because we don't inherit parent's methods
// c1.parentDo("called parentDo on childAlias") // NOGO c1.parentDo undefined
// CAN do because we inherit the parent's methods
c2.parentDo("called parentDo on childObjParent")
c3.parentDo("called parentDo on childPointerParent")
c4.parentDo("called parentDo on childPointerParent")
}
答案 2 :(得分:0)
扩展其他答案之一,在我的情况下,父级是一个数组。如果你 想要添加方法,还要访问父方法,必须要换行 定义类型时,声明变量时换行:
package main
type parent []int
func (p parent) first() int {
return p[0]
}
type child struct {
parent
}
func (c child) second() int {
return c.parent[1]
}
func main() {
a := child{
parent{1, 2},
}
first := a.first()
second := a.second()
println(first == 1, second == 2)
}