Gob не может закодировать карту с нулевым значением указателя - PullRequest
0 голосов
/ 06 июня 2018

Код 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) кодировать все ключи, даже если значения имеют нулевое значение.С текущим состоянием вещей, является ли наилучшей практикой рекурсивное сканирование моей структуры, чтобы увидеть, есть ли какие-либо значения карты nil, и удалить эти ключи, если так?Если эта проверка требуется, кажется, что ответственность должна лежать на пакете 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 Ответ

0 голосов
/ 06 июня 2018

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

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

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

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

...