Redigo и Gob, как получить фрагменты данных GOB

go encoding gob redigo

861 просмотра

1 ответ

Я вставляю свои базы данных в redis с помощью команды "RPUSH".

// object is of type interface

var network bytes.Buffer
gob.NewEncoder(&network)
enc.Encode(object /* interface{} */)

redis.String(d.Conn.Do("RPUSH", "objects", network.String()))

Redigo делает то, что я ожидаю, он толкает всю структуру данных в кодировке gob.

Сейчас я пытаюсь вернуть их

sall, _ := redis.Strings(d.Conn.Do("LRANGE", "todos", "0", "-1"))
fmt.Printf("%T", sall) // type []string as expected

// At this point, I have no idea if I should store the data in a buffer, or convert it directly as bytes. actually, here I'm lost
var network bytes.Buffer
var object []interface{}


dec := gob.NewDecoder(network)
err := dec.Decode(inout)
fmt.Printf("%v", err) // decode error:EOF

Как лучше всего их декодировать? Я хотел бы вернуть их как кусок интерфейса {}. Но даже если мой объект закодирован как данные gob. Они выдвигаются способом redis, поэтому его можно рассматривать как срез с точки зрения Гоба?

Я мог бы перебрать другой список и декодировать их один за другим. Но я не уверен в эффективности. Я предполагаю, что gob хочет структуру фрагмента, закодированную на его пути. Итак, мой вопрос: есть ли хитрость для того, чтобы эффективно декодировать мой фрагмент данных gob как совокупность структуры данных? Или я должен хранить свою структуру данных другим способом (я предполагаю, что хранение моих данных с помощью RPUSH может предотвратить неатомные манипуляции)

Автор: Mr Bonjour Источник Размещён: 08.11.2019 11:04

Ответы (1)


1 плюс

Решение

Команда LRANGE возвращает список. Используйте redis.ByteSlices, чтобы получить этот список в виде байта [] []. Расшифруйте каждый гоб в списке:

items, err := redis.ByteSlices(d.Conn.Do("LRANGE", "objects", "0", "-1"))
if err != nil {
   // handle error
}
var values []*Object
for _, item := range items {
    var v Object
    if err := gob.NewDecoder(bytes.NewReader(item)).Decode(&v); err != nil {
        // handle error
    }
    values = append(values, &v)
}

Это предполагает, что новый gob.Encoder был создан для каждого значения, вставленного в список.

Если приложение не обращается к элементам списка независимо в Redis, то gob кодирует весь список и сохраняет его как массивную строку:

 var values []*Object
 var buf bytes.Buffer
 if err := gob.NewEncoder(&buf).Encode(values); err != nil {
     // handle error
 }
 if _, err := d.Conn.Do("SET", "objects", buf.Bytes()); err != nil {
     // handler error
 }

Вот как это расшифровать:

items, err := redis.Bytes(d.Conn.Do("GET", "objects"))
if err != nil {
    // handle error
}
var values []*Objects
if err := gob.NewDecoder(items).Decode(&values); err != nil {
    // handle error
}

Вот отрывок из этой строки кода из вопроса:

 redis.String(d.Conn.Do("RPUSH", "objects", network.String()))

Используйте network.Bytes (), чтобы избежать выделения строк. Используйте redis.Int для декодирования целочисленного возвращаемого значения из RPUSH. Напишите код как:

 n, err := redis.Int(d.Conn.Do("RPUSH", "objects", network.Bytes()))

или если вас не волнует количество элементов, возвращаемых из списка, запишите его как:

 _, err := d.Conn.Do("RPUSH", "objects", network.Bytes())
Автор: Cerise Limón Размещён: 20.08.2016 01:21
Вопросы из категории :
32x32