在Golang中,可以使用反射(reflection)来动态遍历多个包中具有相同名称的结构体和函数,从而避免重复代码。以下是一个实现方案:
package main
import (
"fmt"
"reflect"
"yourproject/testpkg1"
"yourproject/testpkg2"
"yourproject/testpkg3"
)
// 定义测试包接口
type TestPackage interface {
GetTestCases() []TestCase
ProcessData(data interface{}) error
}
type TestCase struct {
Name string
Data interface{}
}
// 统一测试运行器
func RunTests(pkg interface{}) {
v := reflect.ValueOf(pkg)
// 获取测试用例列表
testCasesMethod := v.MethodByName("GetTestCases")
if testCasesMethod.IsValid() {
results := testCasesMethod.Call(nil)
if len(results) > 0 {
testCases := results[0].Interface().([]TestCase)
// 遍历并执行每个测试用例
for _, tc := range testCases {
fmt.Printf("Running test: %s\n", tc.Name)
// 调用处理函数
processMethod := v.MethodByName("ProcessData")
if processMethod.IsValid() {
processResults := processMethod.Call([]reflect.Value{
reflect.ValueOf(tc.Data),
})
if len(processResults) > 0 {
if err, ok := processResults[0].Interface().(error); ok && err != nil {
fmt.Printf("Test %s failed: %v\n", tc.Name, err)
}
}
}
}
}
}
}
func main() {
// 导入的测试包实例
packages := []interface{}{
testpkg1.TestPackage{},
testpkg2.TestPackage{},
testpkg3.TestPackage{},
}
// 遍历所有包执行测试
for _, pkg := range packages {
fmt.Printf("Testing package: %T\n", pkg)
RunTests(pkg)
}
}
假设你的测试包结构如下:
// testpkg1/testpkg1.go
package testpkg1
type TestPackage struct{}
func (tp TestPackage) GetTestCases() []TestCase {
return []TestCase{
{Name: "Test1", Data: "data1"},
{Name: "Test2", Data: 123},
}
}
func (tp TestPackage) ProcessData(data interface{}) error {
fmt.Printf("Processing data: %v\n", data)
return nil
}
// testpkg2/testpkg2.go
package testpkg2
type TestPackage struct{}
func (tp TestPackage) GetTestCases() []TestCase {
return []TestCase{
{Name: "TestA", Data: []string{"a", "b"}},
{Name: "TestB", Data: map[string]int{"x": 1}},
}
}
func (tp TestPackage) ProcessData(data interface{}) error {
fmt.Printf("Processing complex data: %v\n", data)
return nil
}
这个方案通过反射动态调用每个包中相同名称的方法,实现了代码复用。所有测试包只需要遵循相同的接口约定(包含GetTestCases和ProcessData方法),主测试运行器就能统一处理。