在函数中定义本地类型和方法?

Define type and method local in a func?

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

func InsertRow(rec []string) error

这个接口的实现有不同的类型。现在我想用“去测试”来测试这个。在这种情况下,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'

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

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

Spec: Declarations and scope:

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

查看相关:

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

例如:

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.

上试用