首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将地图序列化成采空区后的DeepEqual不正确

将地图序列化成采空区后的DeepEqual不正确
EN

Stack Overflow用户
提问于 2018-06-06 15:32:21
回答 1查看 332关注 0票数 2

我在reflect.DeepEqual中遇到了一些奇怪的行为。我有一个map[string][]string类型的对象,其中一个键的值是一个空片段。当我使用gob对这个对象进行编码,然后将其解码为另一个映射时,根据reflect.DeepEqual,这两个映射并不相等(尽管内容是相同的)。

代码语言:javascript
复制
package main

import (
    "fmt"
    "bytes"
    "encoding/gob"
    "reflect"
)

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

    // Encode m0 to bytes
    var network bytes.Buffer
    enc := gob.NewEncoder(&network)
    enc.Encode(m0)

    // Decode bytes into a new map m2
    dec := gob.NewDecoder(&network)
    m2 := make(map[string][]string)
    dec.Decode(&m2)

    fmt.Printf("%t\n", reflect.DeepEqual(m0, m2)) // false
    fmt.Printf("m0: %+v != m2: %+v\n", m0, m2) // they look equal to me!
}

输出:

代码语言:javascript
复制
false
m0: map[apple:[]] != m2: map[apple:[]]

几个跟踪实验中的笔记:

如果我将m0["apple"]的值设置为非空片(例如m0["apple"] = []string{"pear"} ),那么DeepEqual返回true。

如果将值保留为空片,但从零开始构造相同的映射,而不是使用gob,则DeepEqual返回true:

代码语言:javascript
复制
m1 := make(map[string][]string)
m1["apple"] = []string{}
fmt.Printf("%t\n", reflect.DeepEqual(m0, m1)) // true!

因此,严格地说,DeepEqual如何处理空片并不是一个问题;它与gob的序列化之间存在一些奇怪的交互。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-06 15:42:03

这是因为您编码了一个空的片,在解码过程中,encoding/gob包只在提供的(要解码的目标)不足以容纳编码值的情况下分配一个片。这记录在:gob:类型和值:上。

通常,如果需要分配,解码器将分配内存。否则,它将用从流中读取的值更新目标变量。

由于有0种编码元素,而且nil片完全能够容纳0种元素,所以不会分配任何切片。如果我们将切片与nil的比较结果打印出来,我们就可以验证这一点。

代码语言:javascript
复制
fmt.Println(m0["apple"] == nil, m2["apple"] == nil)

上面的输出是(在围棋游乐场上尝试一下):

代码语言:javascript
复制
true false

请注意,fmt包以相同的方式打印nil切片值和空片:作为[],您不能依赖其输出来判断切片是否为nil

reflect.DeepEqual()对一个nil片和一个空的但非nil的片进行不同的处理(非深度相等):

请注意,非零空片和零片(例如,[]字节{}和[]字节( nil ))并不完全相等。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50724254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档