如何在现有的types中添加新的方法?

我想在大猩猩/多路复用的路由和路由器types上添加一个便利的使用方法:

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) } 

但编译器通知我

无法在非本地typesmux.Router上定义新方法

那么我将如何实现呢? 我是否创build一个具有匿名mux.Route和mux.Router字段的新结构types? 或者是其他东西?

正如编译器提到的,你不能在另一个包中扩展现有的types。 您可以按如下方式定义自己的别名或子包:

 type MyRouter mux.Router func (m *MyRouter) F() { ... } 

或通过embedded原始路由器:

 type MyRouter struct { *mux.Router } func (m *MyRouter) F() { ... } ... r := &MyRouter{router} rF() 

我想在这里扩展@jimt给出的答案。 这个答案是正确的,帮助我在整理这个问题上做出了巨大的贡献。 但是,有两个方法(别名,embedded),我有麻烦的一些警告。

注意 :我使用的是父母和孩子的条款,但我不确定这是最好的组成。 基本上,父母是您想要在本地修改的types。 子是试图实现该修改的新types。

方法1 – 别名

 type child parent // or type MyThing imported.Thing 
  • 提供对字段的访问。
  • 不提供访问方法。

方法2 – embedded( 官方文档 )

 type child struct { parent } // or with import and pointer type MyThing struct { *imported.Thing } 
  • 提供对字段的访问。
  • 提供对这些方法的访问。
  • 初始化需要考虑。

概要

  • 使用组合方法,如果embedded式父代是一个指针,它将不会初始化。 父母必须分开初始化。
  • 如果embedded的父对象是一个指针,并且在初始化子对象时没有初始化,则会出现一个零指针解引用错误。
  • 别名和embedded情况都提供对父项字段的访问。
  • 别名不允许访问父项的方法,但embedded父项。

你可以在下面的代码中看到这个。

在操场上的工作例子

 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") }