Iterating over methods in interface golang

huangapple go评论82阅读模式
英文:

Iterating over methods in interface golang

问题

我正在尝试迭代遍历接口中的所有方法。我找到了一些示例,但似乎无法使我的代码工作。我正在尝试使用封装的结构体在其他包中进行迭代,但在这种情况下,它在同一个包中。

我想要遍历所有的获取函数(在我的示例中只有一个,但在实际情况中有多个)。

我希望输出两行:

  • "2009/11/10 23:00:00 getTenantUUIDQueryInString"
  • "2009/11/10 23:00:00 (tenant_uuid IN (UUID_TO_BIN('8df030a1-a057-4f53-a011-a2b1cff673a1'),UUID_TO-BIN('9df030a1-a057-4f53-a011-a2b1cff673a1'))"

但是,我只得到第一行,然后出现错误:

  • "2009/11/10 23:00:00 getTenantUUIDQueryInString"
  • "panic: reflect: call of reflect.Value.Call on zero Value"

以下是在Go Playground上的代码:https://go.dev/play/p/YsnJ46QnifT

package main

import (
	"fmt"
	"log"
	"reflect"
	"strings"

	"github.com/google/uuid"
)

func main() {
	pipedTenantUUIDs := "8df030a1-a057-4f53-a011-a2b1cff673a1|8df030a1-a057-4f53-a011-a2b1cff673a1"
	so, responseCode, err := createTenantSearch(pipedTenantUUIDs)
	if err != nil {
		log.Println(err, responseCode)
	}

	t := reflect.TypeOf(&so).Elem()
	v := reflect.ValueOf(&so)

	for i := 0; i < t.NumMethod(); i++ {
		method := t.Method(i)
		if strings.HasPrefix(method.Name, "get") {
			log.Println(method.Name)
			whereVal := v.MethodByName(method.Name).Call(nil)
			log.Println(whereVal[0])
		}
	}
}

// 我希望输出两行
// "2009/11/10 23:00:00 getTenantUUIDQueryInString"
// "2009/11/10 23:00:00 (tenant_uuid IN (UUID_TO_BIN('8df030a1-a057-4f53-a011-a2b1cff673a1'),UUID_TO-BIN('9df030a1-a057-4f53-a011-a2b1cff673a1'))"
//
// 但是我只得到第一行,然后出现错误
// "2009/11/10 23:00:00 getTenantUUIDQueryInString"
// "panic: reflect: call of reflect.Value.Call on zero Value"
// 这是我的设置方式

type iTenantSearch interface {
	mapTenantUUID(pipedString string) error
	getTenantUUIDQueryInString() string
}

type tenantSearch struct {
	tenantUUID []uuid.UUID
}

func (ts *tenantSearch) mapTenantUUID(pipedString string) error {
	splitString := strings.Split(pipedString, "|")

	for i := 0; i < len(splitString); i++ {
		parsedUUID, err := uuid.Parse(splitString[i])
		if err != nil {
			ts.tenantUUID = []uuid.UUID{}
			return fmt.Errorf("tenant uuid failed to parse: %s", err)
		}
		ts.tenantUUID = append(ts.tenantUUID, parsedUUID)
	}
	return nil
}

func (ts *tenantSearch) getTenantUUIDQueryInString() string {
	inString := ""
	if ts.tenantUUID != nil {
		inString = inString + `(tenant_uuid IN (`
		for i, s := range ts.tenantUUID {
			if i == (len(ts.tenantUUID) - 1) {
				inString = inString + `UUID_TO_BIN('` + s.String() + `')`
			} else {
				inString = inString + `UUID_TO_BIN('` + s.String() + `'),`
			}
		}
		inString = inString + `))`
	}
	return inString
}

func createTenantSearch(tenantUUIDs string) (iTenantSearch, int, error) {
	var tso tenantSearch

	if tenantUUIDs != "" {
		err := tso.mapTenantUUID(tenantUUIDs)
		return nil, 400, err
	}
	return &tso, 200, nil
}
英文:

I am trying to iterate over all methods in an interface. I have found a few examples - but I can't seem to get mine to work. I am trying to do so with an encapsulated struct that I am using in other packages - but for this case - it is within the same package.

I am trying to iterate over all of the get functions (in my example I have only one - but in real life I have several

I want my output to be two lines

  • "2009/11/10 23:00:00 getTenantUUIDQueryInString"
  • "2009/11/10 23:00:00 (tenant_uuid IN (UUID_TO_BIN('8df030a1-a057-4f53-a011-a2b1cff673a1'),UUID_TO-BIN('9df030a1-a057-4f53-a011-a2b1cff673a1'))"

Instead, I get the first line and then panic

  • "2009/11/10 23:00:00 getTenantUUIDQueryInString"
  • "panic: reflect: call of reflect.Value.Call on zero Value"

here is is on go playground https://go.dev/play/p/YsnJ46QnifT

package main
import (
&quot;fmt&quot;
&quot;log&quot;
&quot;reflect&quot;
&quot;strings&quot;
&quot;github.com/google/uuid&quot;
)
func main() {
pipedTenantUUIDs := &quot;8df030a1-a057-4f53-a011-a2b1cff673a1|8df030a1-a057-4f53-a011-a2b1cff673a1&quot;
so, responseCode, err := createTenantSearch(pipedTenantUUIDs)
if err != nil {
log.Println(err, responseCode)
}
t := reflect.TypeOf(&amp;so).Elem()
v := reflect.ValueOf(&amp;so)
for i := 0; i &lt; t.NumMethod(); i++ {
method := t.Method(i)
if strings.HasPrefix(method.Name, &quot;get&quot;) {
log.Println(method.Name)
whereVal := v.MethodByName(method.Name).Call(nil)
log.Println(whereVal[0])
}
}
}
// I want my output to be two lines
//  &quot;2009/11/10 23:00:00 getTenantUUIDQueryInString&quot;
//  &quot;2009/11/10 23:00:00 (tenant_uuid IN (UUID_TO_BIN(&#39;8df030a1-a057-4f53-a011-a2b1cff673a1&#39;),UUID_TO-BIN(&#39;9df030a1-a057-4f53-a011-a2b1cff673a1&#39;))&quot;
//
// instead i get a the first line and then panic
// &quot;2009/11/10 23:00:00 getTenantUUIDQueryInString&quot;
// &quot;panic: reflect: call of reflect.Value.Call on zero Value&quot;
// this is how i have everything set up
type iTenantSearch interface {
mapTenantUUID(pipedString string) error
getTenantUUIDQueryInString() string
}
type tenantSearch struct {
tenantUUID []uuid.UUID
}
func (ts *tenantSearch) mapTenantUUID(pipedString string) error {
splitString := strings.Split(pipedString, &quot;|&quot;)
for i := 0; i &lt; len(splitString); i++ {
parsedUUID, err := uuid.Parse(splitString[i])
if err != nil {
ts.tenantUUID = []uuid.UUID{}
return fmt.Errorf(&quot;tenant uuid failed to parse: %s&quot;, err)
}
ts.tenantUUID = append(ts.tenantUUID, parsedUUID)
}
return nil
}
func (ts *tenantSearch) getTenantUUIDQueryInString() string {
inString := &quot;&quot;
if ts.tenantUUID != nil {
inString = inString + `(tenant_uuid IN (`
for i, s := range ts.tenantUUID {
if i == (len(ts.tenantUUID) - 1) {
inString = inString + `UUID_TO_BIN(&#39;` + s.String() + `&#39;)`
} else {
inString = inString + `UUID_TO_BIN(&#39;` + s.String() + `&#39;),`
}
}
inString = inString + `))`
}
return inString
}
func createTenantSearch(tenantUUIDs string) (iTenantSearch, int, error) {
var tso tenantSearch
if tenantUUIDs != &quot;&quot; {
err := tso.mapTenantUUID(tenantUUIDs)
return nil, 400, err
}
return &amp;tso, 200, nil
}

答案1

得分: 0

我找到了答案,感谢Cerise Limón。以下是修正后的代码:

  1. 在create函数中修复了逻辑问题
  2. 导出了我的get方法
  3. 将v设置为一个iTenantSearch:v := reflect.ValueOf(&so).Elem() - Cerise Limón

这是在https://go.dev/play/p/7fG9FcIr6vQ 上运行的代码:

package main

import (
	"fmt"
	"log"
	"reflect"
	"strings"

	"github.com/google/uuid"
)

func main() {
	pipedTenantUUIDs := "8df030a1-a057-4f53-a011-a2b1cff673a1|8df030a1-a057-4f53-a011-a2b1cff673a1"
	so, responseCode, err := createTenantSearch(pipedTenantUUIDs)
	if err != nil {
		log.Println(err, responseCode)
	}

	t := reflect.TypeOf(&so).Elem()
	v := reflect.ValueOf(&so).Elem()

	for i := 0; i < t.NumMethod(); i++ {

		method := t.Method(i)
		if strings.HasPrefix(method.Name, "Get") {
			log.Println(method.Name)
			whereVal := v.MethodByName(method.Name).Call(nil)
			log.Println(whereVal[0])
		}
	}

}

type iTenantSearch interface {
	mapTenantUUID(pipedString string) error
	GetTenantUUIDQueryInString() string
}

type tenantSearch struct {
	tenantUUID []uuid.UUID
}

func (ts *tenantSearch) mapTenantUUID(pipedString string) error {
	splitString := strings.Split(pipedString, "|")

	for i := 0; i < len(splitString); i++ {
		parsedUUID, err := uuid.Parse(splitString[i])
		if err != nil {
			ts.tenantUUID = []uuid.UUID{}
			return fmt.Errorf("tenant uuid failed to parse: %s", err)
		}
		ts.tenantUUID = append(ts.tenantUUID, parsedUUID)
	}
	return nil
}

func (ts *tenantSearch) GetTenantUUIDQueryInString() string {
	inString := ""
	if ts.tenantUUID != nil {
		inString = inString + `(tenant_uuid IN (`
		for i, s := range ts.tenantUUID {
			if i == (len(ts.tenantUUID) - 1) {
				inString = inString + `UUID_TO_BIN('` + s.String() + `')`
			} else {
				inString = inString + `UUID_TO_BIN('` + s.String() + `'),`
			}
		}
		inString = inString + `))`
	}
	return inString
}

func createTenantSearch(tenantUUIDs string) (iTenantSearch, int, error) {
	var tso tenantSearch

	err := tso.mapTenantUUID(tenantUUIDs)
	if err != nil {
		return nil, 400, err
	}
	return &tso, 200, nil
}

希望对你有帮助!

英文:

I found the answer thanks to Cerise Limón.. here is the corrected code...

  1. fixed logic in create function
  2. exported my get method
  3. Set v to an iTenantSearch: v := reflect.ValueOf(&so).Elem() –
    Cerise Limón

here is the working code on https://go.dev/play/p/7fG9FcIr6vQ

package main
import (
&quot;fmt&quot;
&quot;log&quot;
&quot;reflect&quot;
&quot;strings&quot;
&quot;github.com/google/uuid&quot;
)
func main() {
pipedTenantUUIDs := &quot;8df030a1-a057-4f53-a011-a2b1cff673a1|8df030a1-a057-4f53-a011-a2b1cff673a1&quot;
so, responseCode, err := createTenantSearch(pipedTenantUUIDs)
if err != nil {
log.Println(err, responseCode)
}
t := reflect.TypeOf(&amp;so).Elem()
v := reflect.ValueOf(&amp;so).Elem()
for i := 0; i &lt; t.NumMethod(); i++ {
method := t.Method(i)
if strings.HasPrefix(method.Name, &quot;Get&quot;) {
log.Println(method.Name)
whereVal := v.MethodByName(method.Name).Call(nil)
log.Println(whereVal[0])
}
}
}
type iTenantSearch interface {
mapTenantUUID(pipedString string) error
GetTenantUUIDQueryInString() string
}
type tenantSearch struct {
tenantUUID []uuid.UUID
}
func (ts *tenantSearch) mapTenantUUID(pipedString string) error {
splitString := strings.Split(pipedString, &quot;|&quot;)
for i := 0; i &lt; len(splitString); i++ {
parsedUUID, err := uuid.Parse(splitString[i])
if err != nil {
ts.tenantUUID = []uuid.UUID{}
return fmt.Errorf(&quot;tenant uuid failed to parse: %s&quot;, err)
}
ts.tenantUUID = append(ts.tenantUUID, parsedUUID)
}
return nil
}
func (ts *tenantSearch) GetTenantUUIDQueryInString() string {
inString := &quot;&quot;
if ts.tenantUUID != nil {
inString = inString + `(tenant_uuid IN (`
for i, s := range ts.tenantUUID {
if i == (len(ts.tenantUUID) - 1) {
inString = inString + `UUID_TO_BIN(&#39;` + s.String() + `&#39;)`
} else {
inString = inString + `UUID_TO_BIN(&#39;` + s.String() + `&#39;),`
}
}
inString = inString + `))`
}
return inString
}
func createTenantSearch(tenantUUIDs string) (iTenantSearch, int, error) {
var tso tenantSearch
err := tso.mapTenantUUID(tenantUUIDs)
if err != nil {
return nil, 400, err
}
return &amp;tso, 200, nil
}

huangapple
  • 本文由 发表于 2022年10月9日 13:11:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/74002279.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定