我想包装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)"))
}
有没有更好的方法来处理这种情况?
答案 0 :(得分:2)
你也可以嵌入
dfRes <- setNames( data.frame(Result), rownames(Teste) )
你将获得免费的mySelection的goquery.Selection方法,可以添加或覆盖一些。
答案 1 :(得分:1)
嗯,有几种方法可以“处理这个问题”。但请不要将其命名为Get()
:it isn't idiomatic。
从最佳实践的角度来看,我建议:
原因很多。但是对于Go来说,最好保持简单 - 这归结为一个问题:你想要对代码进行单元测试吗?
如果答案是肯定的,那么我绝不会直接使用第三方包。我用他自己的界面包装他们的包。然后,在我的所有代码中使用(注入)该接口,以便允许我在单元测试中模拟它。
同样有几种模式和观点;但是,我将展示一个允许进行单元测试的包装器。
package mypackage
import (
"path/to/goquery.Selection"
)
var _mySelector *mySelector // Go stdlib uses underscores for private types
type mySelector interface {
Html() string
...
}
type MySelector struct {
}
func (ms *MySelector) Html() {
// your custom version
}
// initialize the global var with your wrapper
func init() {
_mySelector = &MySelector{ ... }
}
package mypackage
func Foo() {
// uses the global var initialized with init()
data := _mySelector.Html()
// IoC using D.I. through constructors
obj := NewSomething(_mySelector)
// IoC using D.I. through methods
result := bar.Process(_mySelector, "input data")
}
package mypackage
import (
"testing"
)
type mockSelector struct {
HtmlWasCalled bool
HtmlReturnsThis string
}
func (ms mockSelector) Html() string {
ms.HtmlWasCalled = true
return ms.HtmlReturnsThis
}
func TestBar(t *testing.T) {
// arrange
// override your global var
oldMS := _mySelector
_mySelector := &mockSelector{
HtmlReturnsThis: "<b>success</b>",
}
// act
// since foo.Bar is using the global var, it now uses
// our mock we set above.
result := foo.Bar("sample input")
// assert
if result != expected {
t.Fail()
}
// put it back the way it was
_mySelector = oldMS
}
func TestFoo(t *testing.T) {
// arrange
mock := &mockSelector{
HtmlReturnsThis: "<b>success</b>",
}
// act
// or, just inject your mock if using IoC
result := bar.Process(mock, "sample input")
// assert
...
}
这使我在单元测试期间不必处理第三方程序包的细微差别。效果很好,除非包的API很大。然后,我甚至质疑为什么我使用包来开始,如果它是那么复杂。