包装类型的惯用方法是什么?

我想包装goquery.Selection以更方便地获取 HTML 和选择器字符串。


要访问 的方法goquery.Selection,我应该Get()在下面的代码中实现一些辅助方法吗?


type MySelection goquery.Selection


// Without this helper method, I should always use type conversion

// to use goquery.Selection's methods.

func (s *MySelection) Get() *goquery.Selection {

    sel := s.(goquery.Selection)

    return sel

}


func (s *MySelection) HTML() string {

    // html, _ := s.Html() <- error

    html, _ := s.Get().Html()

    return html

}


func (s *MySelection) String() string {

    return fmt.Sprintf("%v#%v.%v",

        goquery.NodeName(s.Get()),

        s.Get().AttrOr("id", "(undefined)"),

        s.Get().AttrOr("class", "(undefined)"))

}

有没有更好的方法来处理这种情况?


临摹微笑
浏览 192回答 2
2回答

ABOUTYOU

你也可以嵌入type MySelection struct {&nbsp; &nbsp; goquery.Selection&nbsp; &nbsp; some payload //if needed}并且您将免费获得 MySelection 的 goquery.Selection 方法,并且可以添加或覆盖一些方法。

守着一只汪

嗯,有几种方法可以“处理这个”。但不要说出它的名字Get():它不是惯用的。从最佳实践的角度来看,我建议:将他们的代码与您的代码分离。实现反腐败层(包装他们的包的包装器)造成这种情况的原因很多。但是对于 Go 来说,最好保持简单——这归结为一个问题:你想对你的代码进行单元测试吗?如果答案是肯定的,那么我永远不会直接使用 3rd 方包。我会用我自己的界面包装他们的包。然后,在我的所有代码中使用(注入)该接口,以便我可以在单元测试中模拟它。同样有几种模式和观点;但是,我将展示这个允许单元测试的包装器。goquery_wrapper.gopackage mypackageimport (&nbsp; "path/to/goquery.Selection")var _mySelector *mySelector // Go stdlib uses underscores for private typestype mySelector interface {&nbsp; Html() string&nbsp; ...}type MySelector struct {}func (ms *MySelector) Html() {&nbsp; // your custom version}// initialize the global var with your wrapperfunc init() {&nbsp; _mySelector = &MySelector{ ... }}foo.gopackage mypackagefunc Foo() {&nbsp; // uses the global var initialized with init()&nbsp; data := _mySelector.Html()&nbsp; // IoC using D.I. through constructors&nbsp; obj := NewSomething(_mySelector)&nbsp; // IoC using D.I. through methods&nbsp; result := bar.Process(_mySelector, "input data")}bar_test.gopackage mypackageimport (&nbsp; "testing")type mockSelector struct {&nbsp; HtmlWasCalled bool&nbsp; HtmlReturnsThis string}func (ms mockSelector) Html() string {&nbsp; ms.HtmlWasCalled = true&nbsp; return ms.HtmlReturnsThis}func TestBar(t *testing.T) {&nbsp; // arrange&nbsp; // override your global var&nbsp; oldMS := _mySelector&nbsp; _mySelector := &mockSelector{&nbsp; &nbsp; HtmlReturnsThis: "<b>success</b>",&nbsp; }&nbsp; // act&nbsp; // since foo.Bar is using the global var, it now uses&nbsp; // our mock we set above.&nbsp; result := foo.Bar("sample input")&nbsp; // assert&nbsp; if result != expected {&nbsp; &nbsp; t.Fail()&nbsp; }&nbsp; // put it back the way it was&nbsp; _mySelector = oldMS}func TestFoo(t *testing.T) {&nbsp; // arrange&nbsp; mock := &mockSelector{&nbsp; &nbsp; HtmlReturnsThis: "<b>success</b>",&nbsp; }&nbsp; // act&nbsp; // or, just inject your mock if using IoC&nbsp; result := bar.Process(mock, "sample input")&nbsp; // assert&nbsp; ...}这使我不必在单元测试期间处理 3rd 方包的细微差别。效果很好,除非包的 API 很大。然后,我什至质疑为什么我开始使用这个包,如果它那么复杂。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go