我正在编写一个函数,它将输入数据作为字符串以及要调用的 SHA 算法的位大小。它应该将生成的哈希值作为字节切片返回(第一次尝试):
package main
import (
"crypto/sha256"
"crypto/sha512"
"errors"
"fmt"
)
func main() {
input := "This is a test."
sha256, _ := shaSum(input, 256)
sha384, _ := shaSum(input, 384)
sha512, _ := shaSum(input, 512)
fmt.Println(input, sha256, sha384, sha512)
}
func shaSum(data string, size uint) ([]byte, error) {
input := []byte(data)
switch size {
case 256:
return sha256.Sum256(input), nil
case 384:
return sha512.Sum384(input), nil
case 512:
return sha512.Sum512(input), nil
default:
return nil, errors.New("unsupported sha size")
}
}
当然,这是行不通的:
$ go run shasum.go
# command-line-arguments
./shasum.go:22:23: cannot use sha256.Sum256(input) (type [32]byte) as type []byte in return argument
./shasum.go:24:23: cannot use sha512.Sum384(input) (type [48]byte) as type []byte in return argument
./shasum.go:26:23: cannot use sha512.Sum512(input) (type [64]byte) as type []byte in return argument
所以我试图从哈希函数的返回值中获取一个切片,添加[:]
每次调用后(第二次尝试):
func shaSum(data string, size uint) ([]byte, error) {
input := []byte(data)
switch size {
case 256:
return sha256.Sum256(input)[:], nil
case 384:
return sha512.Sum384(input)[:], nil
case 512:
return sha512.Sum512(input)[:], nil
default:
return nil, errors.New("unsupported sha size")
}
}
这也不起作用:
$ go run shasum.go
# command-line-arguments
./shasum.go:22:30: invalid operation sha256.Sum256(input)[:] (slice of unaddressable value)
./shasum.go:24:30: invalid operation sha512.Sum384(input)[:] (slice of unaddressable value)
./shasum.go:26:30: invalid operation sha512.Sum512(input)[:] (slice of unaddressable value)
所以我试图获取返回值的地址,使用括号来确保首先获取表达式的地址,然后进行切片(第三次尝试):
func shaSum(data string, size uint) ([]byte, error) {
input := []byte(data)
switch size {
case 256:
return (&(sha256.Sum256(input)))[:], nil
case 384:
return (&(sha512.Sum384(input)))[:], nil
case 512:
return (&(sha512.Sum512(input)))[:], nil
default:
return nil, errors.New("unsupported sha size")
}
}
这会产生以下错误消息:
$ go run shasum.go
# command-line-arguments
./shasum.go:22:10: cannot take the address of sha256.Sum256(input)
./shasum.go:24:10: cannot take the address of sha512.Sum384(input)
./shasum.go:26:10: cannot take the address of sha512.Sum512(input)
所以我放弃并使用额外的行来解决它(第四次尝试):
func shaSum(data string, size uint) ([]byte, error) {
input := []byte(data)
switch size {
case 256:
bytes := sha256.Sum256(input)
return bytes[:], nil
case 384:
bytes := sha512.Sum384(input)
return bytes[:], nil
case 512:
bytes := sha512.Sum512(input)
return bytes[:], nil
default:
return nil, errors.New("unsupported sha size")
}
}
最终编译并运行。现在我想知道:为什么第四次尝试有效,而其他尝试(尤其是第三次尝试)却无效?一个好的解决方案是什么样的?有没有办法避免像第四次尝试那样增加额外的行?
EDIT:我的问题的根本问题不是如何从字节数组转换为字节切片,而是我对可寻址性概念缺乏理解,以及如何用惯用的 Go 表达我的问题的解决方案。