Reputation: 3300
I found the following code in crypto/sha256/sha256.go
:
func putUint32(x []byte, s uint32) {
_ = x[3]
x[0] = byte(s >> 24)
x[1] = byte(s >> 16)
x[2] = byte(s >> 8)
x[3] = byte(s)
}
All I see that this assignment to the blank identifier would do is panic if len(x)
wasn't at least 4, which isn't even an effect of the assignment as much as it is of the evaluation of x[3]
. So, wouldn't the following (shorter, more desirable code) be equivalent?
func putUint32(x []byte, s uint32) {
x[3] = byte(s)
x[2] = byte(s >> 8)
x[1] = byte(s >> 16)
x[0] = byte(s >> 24)
}
If so, why wasn't it written this way?
Upvotes: 3
Views: 78
Reputation: 109417
The _ =
assignment itself does nothing, but the index expression assigned to it is there to access the last element needed in the slice before a number of other lower index operations. This is an optimization to hint to the compiler that all the lower index operations on that value are safe, and the bounds checks can be elided. This is often call "Bounds Check Elimination"
The primary reason the latter example isn't used is a second optimization, the bytes need to be read in-order so that the compiler can coalesce them into multi-byte loads.
Upvotes: 7