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

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() *

为了更方便地获取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)"))
}
键入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
}