【问题标题】:How to cast a segment of an array into an array in Go?如何在 Go 中将数组的一部分转换为数组?
【发布时间】:2023-03-22 07:56:01
【问题描述】:

我正在使用哈希函数sha256.Sum256(data []byte) [sha256.Size]byte。 我需要将返回的摘要存储在另一个更大数组的末尾。

var x [sha256.BlockSize+sha256.Size]byte 
? = sha256.Sum256(data)

目前我找到的唯一解决方案如下:

var x [sha256.BlockSize+sha256.Size]byte 
var d = sha256.Sum256(data)
copy(x[sha256.BlockSize:], d[:]) 

是否可以避免这个副本?

【问题讨论】:

    标签: arrays go slice sha256


    【解决方案1】:

    如果你放弃使用sha256.Sum256()函数,你可以避免复制,你首先通过调用sha256.New()创建一个hash.Hash

    使用hash.Hash,您可以使用Hash.Sum() 方法计算摘要,这里重要的是您可以向其传递一个切片,表明您希望将结果附加到该摘要。

    对于目标切片,您可以传递一个切片值,该值指向您想要结果的x 数组中的元素,例如0 长度(结果将被附加到该切片中,而不是填充到其中):

    var x [sha256.BlockSize+sha256.Size]byte
    h := sha256.New()
    h.Write(data)
    h.Sum(x[sha256.BlockSize:sha256.BlockSize])
    

    看这个例子来演示它:

    data := []byte("hello")
    fmt.Println(sha256.Sum256(data))
    
    var x [sha256.BlockSize + sha256.Size]byte
    h := sha256.New()
    h.Write(data)
    res := h.Sum(x[sha256.BlockSize:sha256.BlockSize])
    fmt.Println(res)
    fmt.Println(x)
    

    首先我使用sha256.Sum256() 打印结果,这样我们就有了一个“真实”的结果来比较。然后我调用并打印Hash.Sum() 的结果。最后我们打印x数组来验证结果在里面。

    输出(在Go Playground上试试):

    [44 242 77 186 95 176 163 14 38 232 59 42 197 185 226 158 27 22 30 92 31 167 66 94 115 4 51 98 147 139 152 36] [44 242 77 186 95 176 163 14 38 232 59 42 197 185 226 158 27 22 30 92 31 167 66 94 115 4 51 98 147 139 152 36] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 44 242 77 186 95 176 163 14 38 232 59 42 197 185 226 158 27 22 30 92 31 167 66 94 115 4 51 98 147 139 152 36]

    更新:

    您写道您知道这一点,但故意避免这样做以避免分配hash.Hash。知道sha256.Sum256() 使用与sha256.New() 在后台返回的相同实现,所以这个解决方案很可能不会变慢(没有基准测试)。 您还可以重复使用哈希器!所以实际上这可以更快。要重用,请调用Hash.Reset() 方法。

    更新 #2:

    您表示您必须在每个网络请求中执行此操作。在这种情况下,可能使用sha256.Sum256() 是最好的选择。如果您确实需要提高性能,您可以选择“克隆”sha256 包,在您的克隆版本中,您可以修改Sum256() 函数以接收可以直接存储结果的切片(我链接的其他答案显示了迈出的第一步),但说真的,复制 32 字节(SHA-256 摘要的大小)是如此之快,不值得麻烦,而且性能提升不会很大。

    查看相关问题:How to efficiently hash (SHA 256) in golang data where only the last few bytes changes

    【讨论】:

    • 我意识到了这一点。我使用sha256.Sum256() 是因为我想避免使用sha256.New() 进行分配。
    • @chmike 请阅读我编辑的答案。 sha256.Sum256() 使用 sha256.Hash() 返回的相同哈希器,您可以重用 sha256.New() 返回的 hash.Hash
    • 据我了解代码,sha256.Sum256() 没有分配块。摘要结构在堆栈上。
    • @chmike sha256.Sum256() 也必须分配块,只是它会留在堆栈上。它还必须分配不会在堆栈上的结果,如果你传递一个切片,Hash.Sum() 不会。此外,通过重用hash.Hash,我相信您可以获得更好的性能。有关示例和基准,请参阅链接答案:How to efficiently hash (SHA 256) in golang data where only the last few bytes changes
    • 我刚刚检查过了。 sha256.Sum256() 在堆上有 0 个分配。返回的数组存储在堆栈中。此外,我的基准测试与副本没有显着差异。所以副本可能会被优化掉。
    猜你喜欢
    • 2017-05-15
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    • 2017-10-24
    • 1970-01-01
    • 2017-02-05
    • 2020-05-28
    • 1970-01-01
    相关资源
    最近更新 更多