go - 使用 pg.Array 时如何将 reflect.Pointer() 转换为 []string?

标签 go go-pg

我正在使用 go-pg 编写自定义查询缓存系统,该系统采用传递给查询函数的查询参数并生成用于 Redis 的哈希键。我正在使用 Go 的 reflect 来检查有效的参数类型,直到我使用 pg.Array 作为传递的参数。

Reflect 给了我 reflect.Ptr,但是我如何在调用 switch case block 时提取指针的结构/数组?

func GenerateQueryCacheKey(args ...interface{}) string {
    var argumentString = ""

    for _, arg := range args {

        v := reflect.ValueOf(arg)
        switch v.Kind() {
        case reflect.Array, reflect.Slice:
            ret := make([]interface{}, v.Len())

            for i := 0; i < v.Len(); i++ {
                ret[i] = v.Index(i).Interface()
            }

            GenerateQueryCacheKey(ret...)
        case reflect.Bool:
            argumentString += strconv.FormatBool(v.Bool())
        case reflect.String:
            argumentString += v.String()
        case reflect.Int:
            argumentString += string(v.Int())
        case reflect.Uint:
            argumentString += string(v.Uint())
        case reflect.Float32:
            argumentString += strconv.FormatFloat(v.Float(), 'E', -1, 32)
        case reflect.Invalid:
            log.Printf("Invalid type handle! " + fmt.Sprintf("%T", arg))
            argumentString += "nil"
        case reflect.Ptr:
            p := v.Elem()

            ret := make([]interface{}, p.Len())

            for i := 0; i < p.Len(); i++ {
                ret[i] = p.Index(i).Interface()
            }

            GenerateQueryCacheKey(ret...)
        default:
            log.Printf("Unhandled reflect type supplied! " + fmt.Sprintf("%T %T", arg, v))
            argumentString += "nil"
        }
    }

    h := md5.New()
    io.WriteString(h, argumentString)

    return fmt.Sprintf("%x", h.Sum(nil))
}

pg.Array 定义:https://sourcegraph.com/github.com/lib/pq/-/blob/array.go#L29:6

编辑:发布的链接对 pg.Array 的定义不正确。我不小心从 sourcegraph.com 抓取了错误的库。

最佳答案

通过从反射中恢复并使用更直接的方法来解决。

我只是从 pg 中导入了 types.Array 并创建了一个 interface{} slice ,然后手动将字符串添加到 interface{} slice 中,并使用展开运算符创建了一个递归函数存在。不确定这是否是最佳方法,但目前对我有用。

func GenerateQueryCacheKey(args ...interface{}) string {
    var argumentString = ""

    for _, arg := range args {

        switch v := arg.(type) {
        case bool:
            argumentString += strconv.FormatBool(v)
        case string:
            argumentString += v
        case int:
            argumentString += strconv.Itoa(v)
        case uint64:
            argumentString += string(v)
        case float64:
            argumentString += strconv.FormatFloat(v, 'E', -1, 32)
        case *types.Array:
            stringArrayArgs := make([]interface{}, len(v.Value().([]string)))
            for i, vs := range v.Value().([]string) {
                stringArrayArgs[i] = vs
            }

            argumentString += GenerateQueryCacheKey(stringArrayArgs...)
        case nil:
        default:
            log.Printf("%T was requested and not handled!\n", v)
            argumentString += "nil"
        }
    }

    h := md5.New()
    io.WriteString(h, argumentString)

    return fmt.Sprintf("%x", h.Sum(nil))
}

关于go - 使用 pg.Array 时如何将 reflect.Pointer() 转换为 []string?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55958881/

相关文章:

pointers - 如何跨包中的文件使用全局变量?

go - 使用证书颁发机构签署证书请求

postgresql - 插入关系 go-pg PostgreSQL

postgresql - go-pg UnionAll - 限制整个表达式

go - Go 中的 map - 如何避免双键查找?

go - go中的dialogflow webhook

postgresql - go-pg - 读取更新后返回的 ID

logging - 无法发送 logrus 输出/dev/null

postgresql - 使用 ORM 将任意数据检索到嵌套对象中