Как извлечь данные из интерфейса - PullRequest
0 голосов
/ 26 февраля 2020

Я использую Redi go для получения метрик из Redis. Хотя в пакете есть несколько встроенных помощников для анализа данных в ответах определенных форматов, у меня есть формат, который мне нужен для анализа, который не рассматривается.

Результатом этой команды является тип Interface и он содержит массив неопределенной длины, внутри каждого есть набор данных. Если я распечатываю результат в виде строки, я получаю (разрывы строк добавлены для удобства чтения) ...

[
      [name cgroup1 consumers %!s(int64=2) pending %!s(int64=90) last-delivered-id 1582572156729-0] 
      [name cgroup2 consumers %!s(int64=2) pending %!s(int64=110) last-delivered-id 1582572156729-0]
]

Как бы я go о повторении такого ответа в Go и доступе к данные. Я нашел много примеров, касающихся JSON и демаршалинга, но не нашел ничего похожего на вышеприведенное.

Используемая команда redis была ...

xinfo groups <stream name>

Данные в Redis, выглядит так ...

1) 1) "name"
   2) "cgroup1"
   3) "consumers"
   4) (integer) 2
   5) "pending"
   6) (integer) 90
   7) "last-delivered-id"
   8) "1582572156729-0"
2) 1) "name"
   2) "cgroup2"
   3) "consumers"
   4) (integer) 2
   5) "pending"
   6) (integer) 110
   7) "last-delivered-id"
   8) "1582572156729-0"

Если я распечатаю тип, который он показывает ...

[]interface {}

Другой вопрос, как извлечь информацию, вложенную глубже.

Например,

XINFO STREAM <stream name>

Я могу использовать ScanStruct, чтобы получить все с первого уровня, но не могу получить информацию при первом входе.

My Инфо структура

type Stream struct {
    Length int    `redis:"length"`
    Groups int    `redis:"groups"`
    LastID string `redis:"last-generated-id"`
}

Если я попытаюсь добавить first-entry снизу, я не уверен, какой тип использовать или как получить значение 12 [1] (1582572131616-0)

Пример Redis Output

127.0.0.1:6379> xinfo stream stream1
 1) "length"
 2) (integer) 1200
 3) "radix-tree-keys"
 4) (integer) 12
 5) "radix-tree-nodes"
 6) (integer) 30
 7) "groups"
 8) (integer) 2
 9) "last-generated-id"
10) "1582642828055-10"
11) "first-entry"
12) 1) "1582572131616-0"
    2) 1) "payload"
       2) "message:0"
13) "last-entry"
14) 1) "1582642828055-10"
    2) 1) "payload"
       2) "message:99"

1 Ответ

0 голосов
/ 26 февраля 2020

Используйте redis.Values ​​, чтобы преобразовать interface{} в ломтики. Используйте redis.ScanStruct для установки структурных полей из среза пар имя-значение.

type Group struct {
    Name            string `redis:"name"`
    Consumers       int    `redis:"consumers"`
    Pending         int    `redis:"pending"`
    LastDeliveredID string `redis:"last-delivered-id"`
}

func scanGroups(resp interface{}, err error) ([]*Group, error) {
    // Get slice from resp
    groups, err := redis.Values(resp, err)
    if err != nil {
        return nil, err
    }

    var result []*Group

    // For each group
    for _, g := range groups {

        // Get slice for group
        v, err := redis.Values(g, nil)
        if err != nil {
            return nil, err
        }

        // Scan slice to struct
        var group Group
        err = redis.ScanStruct(v, &group)
        if err != nil {
            return nil, err
        }

        // Accumlate result
        result = append(result, &group)
    }
    return result, nil
}

Используйте его следующим образом:

 groups, err := scanGroups(conn.Do("XINFO", "GROUPS", "mystream"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...