-1

我正在开发一个 Go 库,我在其中使用该interfacer工具(https://github.com/rjeczalik/interfaces)从结构创建接口,然后运行moqhttps://github.com/matryer /moq ) 为该接口生成一个模拟对象。现在我想编写一个单元测试,如果有人在没有更新接口和模拟的情况下将导出的方法添加到结构中,该测试将失败。

在高层次上,在我看来,我可以reflect.Value同时获取接口和结构并调用NumMethod()它们,然后检查数字是否相等。然而,我正在努力实现这个想法。

例如,如果我尝试这个:

package main

import (
    "fmt"
    "reflect"
)

type PersonInterface interface {
    GetName() string
}

type Person struct {
    Name string
}

func (person *Person) GetName() string {
    return person.Name
}

func main() {
    person := Person{}
    v := reflect.ValueOf(&person)
    fmt.Println(v.NumMethod())

    var personInterface PersonInterface
    w := reflect.ValueOf(personInterface)
    fmt.Println(w.NumMethod())
}

我可以调用 get the number of methods person,但不是 of the personInterface,因为这会因错误消息而恐慌

reflect: 在零值上调用 reflect.Value.NumMethod

这是完整的错误:

> go run assert_struct.go
1
panic: reflect: call of reflect.Value.NumMethod on zero Value

goroutine 1 [running]:
reflect.Value.NumMethod(0x0, 0x0, 0x0, 0x1)
    /usr/local/Cellar/go@1.12/1.12.12/libexec/src/reflect/value.go:1262 +0xc1
main.main()
    /Users/kurt/Documents/Scratch/assert_struct.go:27 +0x1a5
exit status 2

如何获得由 实现的方法的数量interface,更一般地说,我将如何检查接口是否实现了结构的所有导出方法?

4

1 回答 1

1

要将mkopriva的 Go Playground 注释转换为答案,reflect.ValueOf()需要在指向接口 ( PersonInterface) 的指针上调用,然后Elem()需要在该指针上调用:

package main

import (
    "fmt"
    "reflect"
)

type PersonInterface interface {
    GetName() string
}

type Person struct {
    Name string
}

func (person *Person) GetName() string {
    return person.Name
}

func main() {
    person := Person{}
    v := reflect.ValueOf(&person)
    fmt.Println(v.NumMethod())

    var personInterface PersonInterface
    w := reflect.ValueOf(&personInterface)
    fmt.Println(w.Elem().NumMethod())
}

这实际上类似于“反射的三定律”博客 ( https://blog.golang.org/laws-of-reflection ) 中描述的使值可设置的过程。

于 2020-01-20T07:32:17.983 回答