Go 包装类型的惯用方法是什么?
为了更方便地获取HTML和选择器字符串,我想进行包装 要访问Go 包装类型的惯用方法是什么?,go,type-conversion,Go,Type Conversion,为了更方便地获取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
的方法,我是否应该在以下代码上实现一些辅助方法,例如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)"))
}
键入MySelection goquery.Selection
//如果没有这个helper方法,我应该始终使用类型转换
//使用goquery.Selection的方法。
func(s*MySelection)Get()*goquery.Selection{
sel:=s.(goquery.Selection)
返回sel
}
func(s*MySelection)HTML()字符串{
//html,:=s.html()好吧,有几种方法可以“处理这个问题”。但不要将其命名为Get()
:
从最佳做法的角度来看,我建议:
- 将他们的代码与您的代码分离
- 实现反腐败层(包装其包的包装器)
这样做的原因有很多,但对于Go来说,最好保持它的简单性——这可以归结为一个问题:您想对代码进行单元测试吗
如果答案是肯定的,那么我永远不会直接使用第三方软件包。我会用我自己的接口包装他们的软件包。然后,在我的所有代码中使用(注入)该接口,以便允许我在单元测试中模拟它
还有一些模式和观点;但是,我将展示一个允许单元测试的包装器
goquery_.go
foo.go
巴鲁测试
package-mypackage
进口(
“测试”
)
类型选择器结构{
HtmlWasCalled bool
HTMLReturns此字符串
}
func(ms mockSelector)Html()字符串{
ms.HtmlWasCalled=true
返回ms.HtmlReturnsThis
}
func测试条(t*testing.t){
//安排
//覆盖您的全局变量
oldMS:=\u我的选民
_mySelector:=&mockSelector{
HTMLReturns此:“成功”,
}
//表演
//由于foo.Bar正在使用全局变量,因此它现在使用
//我们在上面设置了我们的模拟。
结果:=foo.Bar(“样本输入”)
//断言
如果结果为!=预期结果{
t、 失败()
}
//把它放回原样
_mySelector=oldMS
}
func TestFoo(t*testing.t){
//安排
mock:=&mockSelector{
HTMLReturns此:“成功”,
}
//表演
//或者,如果使用IoC,只需注入您的模拟
结果:=条形流程(模拟,“样本输入”)
//断言
...
}
这使我不必在单元测试期间处理第三方软件包的细微差别。工作正常,除非软件包的API很大。然后,我甚至会问,如果软件包这么复杂,我为什么要开始使用它。好吧,有几种方法可以“处理这个问题”。但不要把它命名为Get()
:
从最佳做法的角度来看,我建议:
- 将他们的代码与您的代码分离
- 实现反腐败层(包装其包的包装器)
这样做的原因有很多,但对于Go来说,最好保持它的简单性——这可以归结为一个问题:您想对代码进行单元测试吗
如果答案是肯定的,那么我永远不会直接使用第三方软件包。我会用我自己的接口包装他们的软件包。然后,在我的所有代码中使用(注入)该接口,以便允许我在单元测试中模拟它
还有一些模式和观点;但是,我将展示一个允许单元测试的包装器
goquery_.go
foo.go
巴鲁测试
package-mypackage
进口(
“测试”
)
类型选择器结构{
HtmlWasCalled bool
HTMLReturns此字符串
}
func(ms mockSelector)Html()字符串{
ms.HtmlWasCalled=true
返回ms.HtmlReturnsThis
}
func测试条(t*testing.t){
//安排
//覆盖您的全局变量
oldMS:=\u我的选民
_mySelector:=&mockSelector{
HTMLReturns此:“成功”,
}
//表演
//由于foo.Bar正在使用全局变量,因此它现在使用
//我们在上面设置了我们的模拟。
结果:=foo.Bar(“样本输入”)
//断言
如果结果为!=预期结果{
t、 失败()
}
//把它放回原样
_mySelector=oldMS
}
func TestFoo(t*testing.t){
//安排
mock:=&mockSelector{
HTMLReturns此:“成功”,
}
//表演
//或者,如果使用IoC,只需注入您的模拟
结果:=条形流程(模拟,“样本输入”)
//断言
...
}
这使我不必在单元测试期间处理第三方软件包的细微差别。除了软件包的API太大外,它工作得很好。然后,我甚至会问,如果软件包这么复杂,我为什么要开始使用它。你也可以嵌入
type MySelection struct {
goquery.Selection
some payload //if needed
}
您还可以免费使用MySelection的goquery.Selection方法,并可以添加或覆盖某些方法。您还可以嵌入
type MySelection struct {
goquery.Selection
some payload //if needed
}
您将免费获得MySelection的goquery.Selection方法,并可以添加或覆盖某些方法
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
...
}
type MySelection struct {
goquery.Selection
some payload //if needed
}