英文:
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 (
"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])
}
}
}
// 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 a the first line and then panic
// "2009/11/10 23:00:00 getTenantUUIDQueryInString"
// "panic: reflect: call of reflect.Value.Call on zero Value"
// 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, "|")
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
}
答案1
得分: 0
我找到了答案,感谢Cerise Limón。以下是修正后的代码:
- 在create函数中修复了逻辑问题
- 导出了我的get方法
- 将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...
- fixed logic in create function
- exported my get method
- 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 (
"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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论