반응형
Go의 기존 유형에 새 메소드를 추가하는 방법은 무엇입니까?
gorilla/mux
Route 및 Router 유형 에 편리한 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에서 새 메서드를 정의 할 수 없습니다.
그래서 나는 이것을 어떻게 달성 할 수 있습니까? 익명의 mux.Route 및 mux.Router 필드가있는 새 구조체 유형을 생성합니까? 또는 다른 것?
컴파일러에서 언급했듯이 다른 패키지에서 기존 유형을 확장 할 수 없습니다. 다음과 같이 고유 한 별칭 또는 하위 패키지를 정의 할 수 있습니다.
type MyRouter mux.Router
func (m *MyRouter) F() { ... }
또는 원래 라우터를 포함하여 :
type MyRouter struct {
*mux.Router
}
func (m *MyRouter) F() { ... }
...
r := &MyRouter{router}
r.F()
여기 에서 @jimt가 제공 한 답변을 확장하고 싶었 습니다 . 그 대답은 정확하고 이것을 분류하는 데 엄청난 도움이되었습니다. 그러나 두 가지 방법 (별칭, 임베드)에 대해 몇 가지주의 사항이 있습니다.
참고 : 나는 부모와 자식이라는 용어를 사용하지만 그것이 작곡에 가장 적합한 지 잘 모르겠습니다. 기본적으로 parent는 로컬에서 수정하려는 유형입니다. Child는 해당 수정을 구현하려는 새로운 유형입니다.
방법 1-유형 정의
type child parent
// or
type MyThing imported.Thing
- 필드에 대한 액세스를 제공합니다.
- 메소드에 대한 액세스를 제공하지 않습니다.
방법 2-임베딩 ( 공식 문서 )
type child struct {
parent
}
// or with import and pointer
type MyThing struct {
*imported.Thing
}
- 필드에 대한 액세스를 제공합니다.
- 메소드에 대한 액세스를 제공합니다.
- 초기화에 대한 고려가 필요합니다.
요약
- 컴포지션 메서드를 사용하면 포함 된 부모가 포인터 인 경우 초기화되지 않습니다. 부모는 별도로 초기화해야합니다.
- 포함 된 부모가 포인터이고 자식이 초기화 될 때 초기화되지 않으면 nil 포인터 역 참조 오류가 발생합니다.
- 유형 정의와 임베드 케이스는 모두 상위 필드에 대한 액세스를 제공합니다.
- The type definition does not allow access to the parent's methods, but embedding the parent does.
You can see this in the following code.
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")
}
참고URL : https://stackoverflow.com/questions/28800672/how-to-add-new-methods-to-an-existing-type-in-go
반응형
'programing tip' 카테고리의 다른 글
목록을 초기화하는 방법 (0) | 2020.08.23 |
---|---|
선택한 행을 dataTable 또는 ui : repeat 내의 commandLink에 어떻게 전달할 수 있습니까? (0) | 2020.08.23 |
div의 CSS 워드 랩핑 (0) | 2020.08.23 |
C # : 어셈블리의 모든 클래스 나열 (0) | 2020.08.23 |
마우스 커서를 앵커와 같은 스타일로 변경 (0) | 2020.08.23 |