2012-02-23 1 views
0

나는 Go를 선택하기 시작 했으므로 쉽게 이해할 수없는 뭔가를 놓친 경우Go에서 하위 패키지로 패키지를 올바르게 구조화하는 방법 대부분의 방법에서 단일 유형이 수신자가 될 수 있습니까?

어쨌든, 현재 설계 단계에있는 유틸리티 라이브러리를 작성하여 x-go-binding 조금 쉬워졌습니다. (필자는 파이썬과 xpyb로 이것을 해왔다.) 예를 들어, EWMH spec에 정의 된 정보를 쿼리하고 콜백 함수에 키를 바인딩하는 데 도움이 될 것이다. (. 그리고 훨씬 더) 패키지 레이아웃 내 초기 아이디어 그래서, 고려 :

  • 각각 자신의 패키지입니다

  • keybind
  • ewmh
    • xutil. (표준 라이브러리의 이미지 패키지 설정 방법과 비슷합니다.)

      내 상황에 고유 한 점은 거의 모든 x-go-binding 호출이 xgb 연결 객체 또는 루트 창 식별자의 일부 조합을 필요로한다는 것입니다. 따라서과 같이 구조체에이 정보를 저장하기 위해 나에게 의미가 있습니다 : 나는 그렇게처럼 사용할 수있는 공장이 것

      type XUtilConnection struct { 
          conn xgb.Conn 
          root xgb.Id 
          // a few other things, like a mapping of events to callbacks 
      } 
      

      그래야 :

      xconn = xutil.NewXUtilConnection(blah blah) 
      

      를 그리고 수

      keybind.get_keycode("a") 
      ewmh.get_atom("_NET_ACTIVE_WINDOW") 
      
      012 : 같은

      xconn.get_active_window() 
      xconn.bind_key("Shift-a", my_callback_fun) 
      

      도있을 수있다 기능 :처럼 사용할

      물론 내 문제는 수신기가 내 지식으로는 같은 패키지에서 선언 된 유형일 수 있다는 것입니다. 내 패키지를 분리하면 내 하위 패키지에서 XUtilConnection 유형을 수신기로 사용할 수 없습니다.

      필자의 답은이 큰 패키지를 다른 논리 파일로 분리하려고 할 것 같지만 이름 공간이 혼란 스러울 수 있습니다. 예를 들어, EWMH 스펙을 구현하는 데는 아마도 100 개 이상의 함수가 필요합니다.

      XUtilConnection 객체의 각 하위 패키지에 새 컨테이너 유형을 정의 할 수 있다는 것도 알고 있습니다. (저는 이것이 캐스팅을 피하기 위해 단일 멤버 XUtilConnection을 포함하는 구조체 여야한다고 들었습니다.) 그러나 이것은 정말 지저분한 상황 인 것처럼 보이고, 내가 원했던 종류의 의미를 막을 것입니다. (즉, XUtilConnection 구조체를 사용하여 여러 모듈에서 메소드를 호출 할 수 있습니다.)

      내 설계 프로세스의 모든 부분에 대한 조언은 크게 감사하겠습니다. 감사!

    답변

    2

    embedding을 사용하는 것이 좋습니다.유형 *XUtilConnection의 값에

    In package xutil: 
    
        type XUtilConnection struct { 
         *ewmh.EWMH  // Embed all methods of *ewmh.EWMH 
         *keybind.KeyBind // Embed all methods of *keybind.KeyBind 
        } 
    
    In package xutil/ewmh: 
    
        type EWMH struct { 
         Conn xgb.Conn 
         Root xgb.Id 
         // and any additional fields that are needed 
        } 
    
        // Some EWMH methods: 
        func (e *EWMH) GetAtom(name string) { ... } 
        func (e *EWMH) ... 
    
    In package xutil/keybind: 
    
        type KeyBind struct { 
         Conn xgb.Conn 
         Root xgb.Id 
         // and any additional fields that are needed 
        } 
    
        // Some keybind methods: 
        func (k *KeyBind) GetKeyCode(s string) { ... } 
        func (k *KeyBind) ... 
    

    이 직접 EWMH 호출 할 수있게된다 년대와 KeyBind의 방법 : 내가 문제를 정확하게 이해하는 경우

    var c *XUtilConnection = ... 
    c.GetAtom("_NET_ACTIVE_WINDOW") // Call (*emwh.EWMH).GetAtom(string) 
    c.GetKeyCode("a")    // Call (*keybind.KeyBind).GetKeyCode(string) 
    
    +0

    각 패키지에서 구조체를 재정의하지 않고이를 수행 할 수있는 방법이 있습니까? (항상 같을 것입니다.) – BurntSushi5

    +0

    그래서이 접근법에서 두 가지 주요한 문제점을 봅니다 : 1) 모든 패키지에이 구조체를 다시 만들어야하고, 2) 내 ewmh 패키지가 내 keybind 패키지와 대화하기를 원한다면 내가 두 레이어에 임베딩을 수행하기 때문에 더 서투른. 솔직히 정말로 심하게 느껴집니다. 모든 것을 하나의 패키지에 집어 넣는 것이 덜 바람직 할 것 같습니다. 다른 아이디어? – BurntSushi5

    +0

    2) 귀하의 질문에 ewmh 패키지가 keybind와 대화하고 싶다는 표시가 보이지 않았습니다. –

    0

    잘 모르겠어요 (난 패키지 이름을 보면 메소드 수신자로 논의되는 것처럼 보이지만 혼란 스럽습니다.)하지만 구조체 대신 인터페이스를 전달하면 모든 패키지 내에서이를 만족시킬 수 있습니다. 하나는 항상 (완전히 테스트되지 않은 코드) 같은 것을 할 수 있습니다.

    package foo 
    
    type Foo interface { Bar(); Baz() } 
    
    ---- 
    package qux 
    
    import "foo" 
    
    type qux struct { foo.Foo; myStuff t } 
    
    func Foo(f foo.Foo) foo.Foo { 
        return qux{f, &t{}} 
    } 
    
    func (q qux) Bar() { 
        // smthg 
    } 
    

    예 : 패키지 qux의 "override"f.Bar 및 "상속"f.Baz()이 변경되지 않았습니다.

    +0

    내 나쁜 --- 나는 충분히 명확하다고 생각하지 않습니다. 내 말은 'ewmh'패키지는 '* XUtilConnection'을 수신기로 사용하고 'ewmh.do_something_without_XUtilConnection'과 같은 일반 함수를 사용하는 * 두 가지 방법을 사용한다는 것을 의미했습니다. 그렇다고해서 인터페이스가 작동한다고 생각하지 않습니다. Atom은 형식 임베디드 방식으로 응답했습니다 --- 구조체와 함께 작동하지는 못했습니다. 내 문제는 "필자는 내 패키지로 전달해야하는 주를 가지고 있으며 가장 쉬운 방법은 패키지를 필요한 방법으로 수신자로 만드는 것입니다." 나는 인터페이스가 나를 돕는다 고 생각하지 않는다. – BurntSushi5