Chcę dodać wygodną metodę wykorzystania do gorilla/mux
typów tras i routerów:
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)
}
ale kompilator informuje mnie
Nie można zdefiniować nowych metod w mux.Router typu nielokalnego
Więc jak mam to osiągnąć? Czy utworzę nowy typ struktury, który ma anonimowe pola mux.Route i mux.Router? Albo coś innego?
go
extension-methods
Daniel Robinson
źródło
źródło
“extension methods are not object-oriented”
) dla C #, ale patrząc na nie dzisiaj, od razu przypomniałem sobie o interfejsach Go (i jego podejściu do ponownego przemyślenia orientacji obiektowej), a potem miałem to pytanie.Odpowiedzi:
Jak wspomina kompilator, nie można rozszerzyć istniejących typów w innym pakiecie. Możesz zdefiniować własny alias lub pakiet podrzędny w następujący sposób:
type MyRouter mux.Router func (m *MyRouter) F() { ... }
lub osadzając oryginalny router:
type MyRouter struct { *mux.Router } func (m *MyRouter) F() { ... } ... r := &MyRouter{router} r.F()
źródło
mux.Router
wystąpienia doMyRouter
s? np. jeśli masz bibliotekę, która zwraca,mux.Router
ale chcesz użyć nowych metod?Chciałem rozwinąć odpowiedź udzieloną przez @jimt tutaj . Ta odpowiedź jest poprawna i ogromnie pomogła mi w rozwiązaniu tego problemu. Istnieją jednak pewne zastrzeżenia dotyczące obu metod (alias, embed), z którymi miałem problem.
uwaga : używam terminów rodzic i dziecko, chociaż nie jestem pewien, czy jest to najlepsze dla kompozycji. Zasadniczo rodzic to typ, który chcesz zmodyfikować lokalnie. Dziecko to nowy typ, który próbuje zaimplementować tę modyfikację.
Metoda 1 - Definicja typu
type child parent // or type MyThing imported.Thing
Metoda 2 - Osadzanie ( oficjalna dokumentacja )
type child struct { parent } // or with import and pointer type MyThing struct { *imported.Thing }
Podsumowanie
Możesz to zobaczyć w poniższym kodzie.
przykład pracy na placu zabaw
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") }
źródło