【问题标题】:Define type and method local in a func?在 func 中定义本地类型和方法?
【发布时间】:2021-05-17 21:04:34
【问题描述】:

我的代码使用一个功能的接口:

func InsertRow(rec []string) error

这个接口的实现有不同的类型。现在我想用“go test”来测试它。在这种情况下, InsertRow 的实现应该什么都不做:

func (t TestInserter) InsertRow(rec []string) error {
  return nil
}

我可以在测试函数中定义一个内部类型。但现在我也想为这种类型定义一个虚拟方法:

func TestInserter01(t *testing.T) {
  type TestMyInserter struct {} <-- Test type 

  func (t TestMyInserter) InsertRow(rec []string) error { <-- Dummy function on this type.
    return nil
  }

  ... using InsertRow as a parameter in another function ...
}

但这会产生编译错误:

expected operand, found ']'
expected ']', found 'return'

如果我在测试函数之外定义类型和方法,则相同的代码可以工作。 是否可以在测试函数中隐藏测试实现而不在函数外部定义它?我需要其中很多,所以我更愿意在测试函数中本地定义它们。

【问题讨论】:

    标签: go testing types interface local


    【解决方案1】:

    不,这是不可能的。方法声明只能在顶层(任何函数之外)。

    Spec: Declarations and scope:

    Declaration   = ConstDecl | TypeDecl | VarDecl .
    TopLevelDecl  = Declaration | FunctionDecl | MethodDecl .
    

    查看相关:Is it possible to define an anonymous interface implementation in Go?

    请注意,可以使用辅助类型提供“动态”实现。这意味着您将在函数内部提供方法实现,并且借助实现接口的辅助类型,您可以获得“动态”实现。

    例如:

    type Inserter interface {
        InsertRow(rec []string) error
    }
    
    type helper func(rec []string) error
    
    func (h helper) InsertRow(rec []string) error {
        return h(rec)
    }
    
    func main() {
        testInsert := func(rec []string) error {
            return fmt.Errorf("rec: %v", rec)
        }
    
        var i Inserter = helper(testInsert)
    
        err := i.InsertRow([]string{"one", "two"})
        fmt.Println(err)
    }
    

    这将输出(在Go Playground 上尝试):

    rec: [one two]
    

    一个变体可能是一个结构体,它包含方法的函数类型字段。可用于覆盖多种方法:

    type helper struct {
        insertRow func(rec []string) error
    }
    
    func (h helper) InsertRow(rec []string) error {
        return h.insertRow(rec)
    }
    
    func main() {
        h := helper{
            insertRow: func(rec []string) error {
                return fmt.Errorf("rec: %v", rec)
            },
        }
    
        var i Inserter = h
    
        err := i.InsertRow([]string{"one", "two"})
        fmt.Println(err)
    }
    

    这输出相同。在Go Playground 上试试吧。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多