Gob не может закодировать карту с нулевым значением указателя

Код Gob возвращает код ошибки, когда я пытаюсь закодировать карту в указатели, если одно из значений равно nil. Это, кажется, противоречит документации (но я могу неправильно истолковывать значение):

В срезах и массивах, а также на картах передаются все элементы, даже элементы с нулевым значением, даже если все элементы равны нулю.

Код:

package main

import (
    "bytes"
    "encoding/gob"
)

type Dog struct {
    Name string
}

func main() {
    m0 := make(map[string]*Dog)
    m0["apple"] = nil

    // Encode m0 to bytes
    var network bytes.Buffer
    enc := gob.NewEncoder(&network)
    err := enc.Encode(m0)
    if err != nil {
        panic(err) // Output: panic: gob: encodeReflectValue: nil element
    }
}

Выход:

panic: gob: encodeReflectValue: nil element

Есть ли веская причина для неудачи в этом случае? Кажется, что любой из двух очевидных вариантов предпочтительнее отказа: 1) не кодировать ключи со значениями с нулевым значением или 2) кодировать все ключи, даже если значения имеют нулевое значение. С текущим состоянием вещей, является ли лучшая практика для рекурсивного сканирования моей структуры, чтобы увидеть, есть ли какие-либо значения карты ноль, и удалить эти ключи, если так? Если эта проверка требуется, кажется, что ответственность за это должен выполнять пакет encoding/gob, а не пользователь.

Кроме того, правило не просто "gob не может кодировать карты, где ключ имеет значение nil", потому что, если типом значения является срез, то принимается nil:

func main() {
    m0 := make(map[string][]string)
    m0["apple"] = nil

    // Encode m0 to bytes
    var network bytes.Buffer
    enc := gob.NewEncoder(&network)
    err := enc.Encode(m0) // err is nil
    if err != nil {
        panic(err) // doesn't panic
    }
}

1 ответ

Решение

gob закодированный поток не имеет понятия указателей. Если вы кодируете значение указателя, такое как *intуказанное значение будет отправлено, то есть значение типа int, Это преобразование инвертируется на стороне декодера, если необходимо, например, если int значение находится в потоке, для которого *int значение должно быть установлено, указатель (типа *int) будет установлен указатель на декодированный int значение.

Так что, если само значение указателя nilнет значения, что gob пакет может кодировать вместо значения указателя, nil указатель указывает на ничто. Разыменование nil указатель это паника во время выполнения.

Это также задокументировано в gob: Основы:

Указатели не передаются, но передаются то, на что они указывают; то есть значения сглаживаются. Нулевые указатели не допускаются, так как они не имеют значения.

Другие вопросы по тегам