Golang中如何调用另一个类的方法

Golang中如何调用另一个类的方法 我有一个方法,它接收文本作为参数。我想根据传入的参数找到对应的类并运行其方法。如何使用反射来实现这一点? 在我截取的图片中,我可以访问同一类中的方法。但我想要访问不同的类。

image

6 回复

你想构建一个通用的 getType 函数版本,对吧?我认为使用反射是不可能的。

更多关于Golang中如何调用另一个类的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


感谢您的回答。 我认为这张图片能更好地解释我想要什么。

image

你好,欢迎来到论坛。

如果参数只能接受固定数量的已知类型,你可以使用类型开关:

switch v := i.(type) {
case T:
    // 这里 v 的类型是 T
case S:
    // 这里 v 的类型是 S
default:
    // 没有匹配项;这里 v 的类型与 i 相同
}

我找到了解决方案,解决方案是通过访问我要使用的结构体内部的结构体来实现的。

package main

import (
	"reflect"
	ioc "go-kargo-consume/ioc"
	str "go-kargo-consume/structer"
)

func main(){
	setMethod("yurtici")
}

func setMethod(mtd string){
	md := str.Response{Isim: "Mehmet"}
	t := GetCargoType(mtd)
	reflect.New(t).MethodByName("Test").Call([]reflect.Value{reflect.ValueOf(md)})
}

func GetCargoType(company string) reflect.Type {
	switch company {
	case "pts":
		return reflect.TypeOf(pts.PtsStruct{})
	case "yurtici":
		return reflect.TypeOf(yurtici.YurticiStruct{})
	default:
		return nil
	}
}

如果 @jauhararifin 的猜测是正确的,即您想通过名称查找任何类型,那么您无法使用 reflect 包来实现。正如 Go 博客的 反射定律 所说:

  • 反射从接口值到反射对象。
  • 反射从反射对象到接口值。
  • 要修改反射对象,其值必须是可设置的。

(重点是我加的)。换句话说,您需要已经拥有某个类型的值才能对其使用反射。

此外,看起来您实际上是在尝试从包中查找函数。这同样无法实现,因为反射只能检查值的成员(方法、字段、数组/切片元素等),而无法访问全局函数。

尽管如此,我过去有一个项目想要实现这个功能,所以我创建了 GitHub - skillian/pkgsyms: Extension to the reflect package with an API similar to the plugin package. It lets you access packages and their exported constants, functions, variables and types by name.。我根据您的截图整理了这个示例:

package main

import (
	"github.com/skillian/pkgsyms"

	_ "forum.golangbridge.org/golang-call-another-class_25952/pts"
	_ "forum.golangbridge.org/golang-call-another-class_25952/yurtici"
)

// 对于您想要访问其类型的每个包,您都需要添加这些 go:generate 行。
// 这也意味着您必须在每次构建之前运行 `go generate`。
// 或者,您可以将这些 go:generate 行放在包自身内部。

//go:generate pkgsyms -package main -output ptssyms.go -varname ptsPkg forum.golangbridge.org/golang-call-another-class_25952/pts
//go:generate pkgsyms -package main -output yurticisyms.go -varname yurticiPkg forum.golangbridge.org/golang-call-another-class_25952/yurtici

func main() {
	pkg := pkgsyms.Of("forum.golangbridge.org/golang-call-another-class_25952/pts")
	v, err := pkg.Lookup("Test")
	if err != nil {
		panic(err)
	}
	testFunc := v.Get().(func())
	testFunc()
}

在Go中,你可以使用反射(reflect包)根据字符串动态调用不同结构体的方法。以下是一个示例实现:

package main

import (
    "fmt"
    "reflect"
)

// 定义两个不同的类
type ClassA struct{}

func (c *ClassA) Process(text string) string {
    return "ClassA处理: " + text
}

type ClassB struct{}

func (c *ClassB) Process(text string) string {
    return "ClassB处理: " + text
}

func main() {
    // 根据参数选择要调用的类
    className := "ClassA"
    methodName := "Process"
    inputText := "测试文本"
    
    result, err := callMethodByName(className, methodName, inputText)
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    
    fmt.Println(result)
}

func callMethodByName(className, methodName, text string) (string, error) {
    // 创建类实例的映射
    instances := map[string]interface{}{
        "ClassA": &ClassA{},
        "ClassB": &ClassB{},
    }
    
    // 获取对应的类实例
    instance, exists := instances[className]
    if !exists {
        return "", fmt.Errorf("类 %s 不存在", className)
    }
    
    // 使用反射获取方法
    method := reflect.ValueOf(instance).MethodByName(methodName)
    if !method.IsValid() {
        return "", fmt.Errorf("方法 %s 不存在", methodName)
    }
    
    // 准备参数并调用方法
    args := []reflect.Value{reflect.ValueOf(text)}
    results := method.Call(args)
    
    // 处理返回值
    if len(results) > 0 {
        return results[0].String(), nil
    }
    
    return "", nil
}

如果你需要更动态的类创建,可以使用注册模式:

package main

import (
    "fmt"
    "reflect"
)

type Processor interface {
    Process(string) string
}

type ClassA struct{}
func (c *ClassA) Process(text string) string {
    return "ClassA处理: " + text
}

type ClassB struct{}
func (c *ClassB) Process(text string) string {
    return "ClassB处理: " + text
}

var registry = map[string]reflect.Type{
    "ClassA": reflect.TypeOf(ClassA{}),
    "ClassB": reflect.TypeOf(ClassB{}),
}

func createInstance(className string) (Processor, error) {
    if typ, exists := registry[className]; exists {
        instance := reflect.New(typ).Interface()
        return instance.(Processor), nil
    }
    return nil, fmt.Errorf("类 %s 未注册", className)
}

func main() {
    className := "ClassB"
    instance, err := createInstance(className)
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    
    result := instance.Process("动态创建的实例")
    fmt.Println(result)
}

第一个示例展示了如何根据字符串名称调用已存在实例的方法,第二个示例展示了如何动态创建类的实例。注意反射调用会有性能开销,在性能敏感的场景需要谨慎使用。

回到顶部