当前位置: 首页 > 面试题库 >

追加切片后,计算sha256会得出不同的结果,具体取决于是否在之前打印出切片

冯卓
2023-03-14
问题内容

我正在从多个字符串计算sha256。我以特定方式将它们转换为字节片,并将它们全部附加在一起,然后使用内置库计算哈希。但是,根据是否在计算sha256之前打印出切片,我会获得不同的结果。在操场上测试时,我无法复制它。

可以看到经过测试的代码,并可以在https://play.golang.org/p/z8XKx-p9huG上运行,在两种情况下,它实际上都可以提供相同的结果。

func getHash(input1 string, input2hex string, input3hex string, input4 string) (string, error) {
    input1bytes := []byte(input1)
    firstHalfinput1Bytes := input1bytes[:8]
    secondHalfinput1Bytes := input1bytes[8:16]

    input4Bytes := []byte(input4)

    input3Bytes, err := hex.DecodeString(input3hex)
    if err != nil {
        fmt.Println("err " + err.Error())
    }

    input2Bytes, err := hex.DecodeString(input2hex)
    if err != nil {
        fmt.Println("err " + err.Error())
    }

    fullHashInputBytes := append(firstHalfinput1Bytes, input2Bytes...)
    // THIS IS THE OPTIONAL PRINT WHICH CHANGES OUTPUT LOCALLY:
    fmt.Println("fullHashInputBytes", fullHashInputBytes)
    fullHashInputBytes = append(fullHashInputBytes, secondHalfinput1Bytes...)
    fullHashInputBytes = append(fullHashInputBytes, input3Bytes...)
    fullHashInputBytes = append(fullHashInputBytes, input4Bytes...)
    sha256 := sha256.Sum256(fullHashInputBytes)
    for i := 0; i < 8; i++ {
        sha256[i+16] ^= sha256[i+24]
    }
    hash := hex.EncodeToString(sha256[:24])
    fmt.Println("hash", hash)
    return hash, nil
}

操场上的日志是

Hello, playground
fullHashInputBytes [84 72 73 83 73 83 78 79 30 0 22 121 57 203 102 148 210 196 34 172 210 8 160 7]
hash 0161d9de8dd815ca9f4e1c7bb8684562542cc24b1026321c
hash 0161d9de8dd815ca9f4e1c7bb8684562542cc24b1026321c

但是如果我在本地运行完全相同的代码(只需将其复制粘贴到main.go中,然后执行go run main.goor go build .和和./test),我会得到

Hello, playground
fullHashInputBytes [84 72 73 83 73 83 78 79 30 0 22 121 57 203 102 148 210 196 34 172 210 8 160 7]
hash 0161d9de8dd815ca9f4e1c7bb8684562542cc24b1026321c
hash d2de4ffb4e8790b8fd1ceeba726436fd97875a5740c27b47

我使用的是go版本,1.13.4但与存在相同的问题1.10.4。在本地计算机上以及在将其部署到服务器时,我也会遇到相同的问题。


问题答案:

这是因为您fullHashInputBytes通过添加到firstHalfinput1Bytesfirst 来创建:

fullHashInputBytes := append(firstHalfinput1Bytes, input2Bytes...)

这是其中的一部分input1bytes

firstHalfinput1Bytes := input1bytes[:8]

因此,第一个附录可能会覆盖input1bytes索引高于7 的at的内容,实际上是以下内容secondHalfinput1Bytes

secondHalfinput1Bytes := input1bytes[8:16]

因此,稍后还要添加secondHalfinput1Bytes到时fullHashInputBytes,可能最终会添加不同的内容。

这很可能不是您想要的。

如果您做到“干净”:

var fullHashInputBytes []byte
fullHashInputBytes = append(fullHashInputBytes, firstHalfinput1Bytes...)
fullHashInputBytes = append(fullHashInputBytes, input2Bytes...)
// OPTIONAL print doesn't change anything:
fmt.Println("fullHashInputBytes", fullHashInputBytes)
// ...rest of your appends...

如果在本地或Go Playground上运行,则输出将相同。

为什么行为异常?

您的第一个追加input1bytes是否被覆盖取决于该追加是否可以“就地”执行而不必分配新的后备数组,这取决于firstHalfinput1Bytes“”从input1bytes以下继承的容量:

input1bytes := []byte(input1)
fmt.Println(cap(input1bytes))

该转换
[]byte(input)只保证拥有的字节input1,但该规范并没有规定所产生的切片的容量有多大应该的。它可能取决于平台/体系结构。在Go
Playground上,上述转换导致capacity = 16我在本地amd64建筑上得到capacity = 32

最后一件:[]byte(input)转换结果切片所使用的容量可能取决于您对结果切片的处理方式。如果将其传递给编译器,则编译器可能会决定使用较低的容量,fmt.Println()因为这表明片可能会逃逸。再次,由编译器做出的决定是您无法控制的。

不要依靠这种东西,不要编写依赖于转换结果片的容量的代码。以“干净”的方式进行:不要追加到firstHalfinput1Bytes新的切片上。



 类似资料:
  • 问题内容: package main 在上面提到的程序中,即使我们正在从is [2]到on病房访问元素,并且片中只有2个元素,也没有为is [2:]感到恐慌。为什么会这样呢? 问题答案: 切片表达式的go规范阐明了切片所用索引的要求: 如果0 <=低<=高<=最大<= cap(a),则索引在范围内,否则它们超出范围。 对于索引表达式,相关要求是: 如果0 <= x <len(a),则索引x处于范围

  • 我正在使用enum/switch case和Zeller的公式来表示一年中的哪一天,一个特定的日期将是哪一天。在我实现代码的枚举/开关部分的前几天,我的代码正在打印(如下所示)。在我放入enum/switch大小写之后,当我在DrJava中运行它时,它确实会提示日期、月份和年份,但是一旦它通过switch大小写,就不会打印任何内容

  • 本文向大家介绍Golang slice切片操作之切片的追加、删除、插入等,包括了Golang slice切片操作之切片的追加、删除、插入等的使用技巧和注意事项,需要的朋友参考一下 本文介绍了Golang slice切片操作之切片的追加、删除、插入等,分享给大家,具体如下: 一、一般操作 1,声明变量,go自动初始化为nil,长度:0,地址:0,nil 2,切片的追加,删除,插入操作 3,copy的

  • 所以这个程序要做的是从键盘上获取输入的id、工时和工资。然后,它将计算加班工资、定期工资和总工资。计算完后,必须将应计算的身份证、小时数、工资、加班工资、定期工资和总工资打印到输出中。 而且,雇员的属性和行为应该在雇员类中。

  • 问题内容: 我很好奇拆包切片并将其作为参数发送给可变参数函数。 假设我们有一个带有可变参数的函数: 如果我们不想传入一个接口,它就可以工作,那么我们是否拆包都没关系: 如果我们有一片片的话,那会很棘手。在这里,编译器不允许我们传递解压版本: 错误提示: 在解包参数中不能将sliceOfSlices(类型[] [] interface {})用作类型[] interface {} 我不知道为什么会这

  • 我试图理解如何在Go中操作数据结构,以及它指向指针(带有副本或引用)的方法。 我的代码在Go Playground这里:https://play.golang.org/p/j_06RS5Xcz 我制作了一个结构的切片图,里面还有一个其他东西的切片。 在这里: 我想在以后的程序中附加其他项。似乎我必须使用指针来解决这个问题,但我不知道如何解决。 我的实体应该是这样吗? 如果是这样的话,我应该如何向它