I want to compare output of sha256.Sum256() which is [32]byte with a []byte.
I am getting an error "mismatched types [32]byte and []byte". I am not able to convert []byte to [32]byte.
Is there a way to do this?
You can trivially convert any array ([size]T) to a slice ([]T) by slicing it:
x := [32]byte{}
slice := x[:] // shorthand for x[0:len(x)]
From there you can compare it to your slice like you would compare any other two slices, e.g.
func Equal(slice1, slice2 []byte) bool {
if len(slice1) != len(slice2) {
return false
}
for i := range slice1 {
if slice1[i] != slice2[i] {
return false
}
}
return true
}
Edit: As Dave mentions in the comments, there's also an Equal method in the bytes package, bytes.Equal(x[:], y[:])
I got the answer using this thread
SHA256 in Go and PHP giving different results
converted := []byte(raw)
hasher := sha256.New()
hasher.Write(converted)
return hex.EncodeToString(hasher.Sum(nil)) == encoded
This is not converting [32]byte to []byte but it is using different function which do not give output in [32]byte.
Related
Is it possible to use slices as keys?
There is my attempt:
h := map[[]string]string{
[]string{"a", "b"} : "ab",
}
the compiler gives me an error invalid map key type []string. So either it's not possible or I declared it incorrectly (if so, what would be a correct way?).
However, it is possible to use arrays as map keys:
package main
import "fmt"
func main() {
m := make(map[[2]int]bool)
m[[2]int{1, 2}] = false
fmt.Printf("%v", m)
}
No, slices cannot be used as map keys as they have no equality defined.
Volker already told that this is not possible and I will give a little bit more details of why is it so with examples from the spec.
Map spec tells you:
The comparison operators == and != must be fully defined for operands
of the key type; thus the key type must not be a function, map, or
slice.
It already tells you that the slice can't be a key, but you could have checked it also in the comparison spec:
Slice, map, and function values are not comparable.
This means that also slice can't be a key, an array can be a key. For example you can write:
h := map[[2]string]string{
[2]string{"a", "b"} : "ab",
}
Depending on your requirements and the complexity of your data, you could use a string as a map key and then use a hash of your slice as the map key.
The nice thing is you can use this technique with anything that can be converted to or from a slice of bytes.
Here's a quick way to convert your slice of strings into a slice of bytes:
[]byte(strings.Join([]string{},""))
Here's an example using SHA1:
type ByteSliceMap struct {
buf *bytes.Buffer
m map[string][]byte
}
func (b *ByteSliceMap) key(buf []byte) string {
h := sha1.New()
h.Write(buf)
sum := h.Sum(nil)
return fmt.Sprintf("%x", sum)
}
func (t *ByteSliceMap) value(key []byte) (value []byte, ok bool) {
value, ok = t.m[t.key(key)]
return
}
func (t *ByteSliceMap) add(key, value []byte) {
if t.m == nil {
t.m = make(map[string][]byte)
}
t.m[t.key(key)] = value
}
Working version
One way to get around this problem is to actually create a key from a slice which has well defined comparison operators:
func createKey(s []string) string { return fmt.Sprintf("%q", s) }
m := make(map[string]string)
s := []string{"a","b"}
m[createKey(s)] = "myValue"
In a similar fashion you would have to create functions for creating keys of slices with type different to string.
In my code, I need a function that would return an ordered slice of keys from a map.
m1 := make(map[string]string)
m2 := make(map[string]int)
And now I need to call a function passing both types of maps:
keys1 := sortedKeys(m1)
keys2 := sortedKeys(m1)
Problem: I have to write two functions because the function should consume maps of two different types. At the same time, the body of the function will be the same in both cases.
Question: How can I use a single implementation for two maps? Or is there any other way of solving the problem in an elegant way?
My first idea was to use map[string]interface{} as an argument type, but you can't assign neither map[string]string, nor map[string]int to it.
My code:
func sortedKeys(m map[string]string) []string {
var keys []string
for key := range m {
keys = append(keys, key)
}
sort.Strings(keys)
return keys
}
I would have to repeat the same code but for map[string]int.
You can use interface{} and use reflection for achieving this.
You can write two functions for the same but it is just not scalable, say, you are supporting string and int now but you wish to support int64, float64, bool or struct in the future. Having a common function using map[string]interface{} and using reflection is the way to go.
Suggested Code :
package main
import (
"fmt"
"reflect"
)
func main() {
m1 := make(map[string]string)
m2 := make(map[string]int)
m1["a"] = "b"
m1["b"] = "c"
m2["a"] = 1
m2["b"] = 2
fmt.Println(sortedKeys(m1))
fmt.Println(sortedKeys(m2))
}
// Returns slice of values in the type which is sent to it
func sortedKeys(m interface{}) interface{} {
if m == nil {
return nil
}
if reflect.TypeOf(m).Kind() != reflect.Map {
return nil
}
mapIter := reflect.ValueOf(m).MapRange()
mapVal := reflect.ValueOf(m).Interface()
typ := reflect.TypeOf(mapVal).Elem()
outputSlice := reflect.MakeSlice(reflect.SliceOf(typ), 0, 0)
for mapIter.Next() {
outputSlice = reflect.Append(outputSlice, mapIter.Value())
}
return outputSlice.Interface()
}
Output :
[b c]
[1 2]
https://play.golang.org/p/2fkpydH9idG
I want to use Scan() in package sql, but the number of columns, and hence the number of arguments, will change at runtime. This is the signature of Scan():
func (rs *Rows) Scan(dest ...interface{}) error
According to the documentation, *interface{} is one of the types accepted by Scan(). So I want to create a slice of []*interface{} and that expand as arguments.
This is what I thought would work:
func query(database *sql.DB) {
rows, _ := database.Query("select * from testTable")
for rows.Next() {
data := make([]*interface{}, 2)
err := rows.Scan(data...) // Compilation error
fmt.Printf("%v%v\n", *data[0], *data[1])
if err != nil {
fmt.Println(err.Error())
}
}
}
Compilation fails with cannot use data (type []*interface {}) as type []interface {} in argument to rows.Scan. I thought that data... would expand to &data[0], &data[1], but apparently not. I don't understand the error message. *interface{} is compatible with interface{}, so why can't I expand the slice of pointers to interface types?
This works:
func query(database *sql.DB) {
rows, _ := database.Query("select * from testTable")
for rows.Next() {
data := make([]*interface{}, 2)
err := rows.Scan(&data[0], &data[1]) // Only changed this line
fmt.Printf("%v%v\n", *data[0], *data[1]) // Outputs "[48][116 101 120 116]"
if err != nil {
fmt.Println(err.Error())
}
}
}
I can't use this however, because the number of columns is unknown at compile time. How can I write this code so that I can pass a variable number of *interface{} to rows.Scan()?
First, you must not use []*interface{} slice of pointers to interface rather than []interface{} where the interfaces are pointers. []*interface{} is different from []interface{}. Just create a slice of interfaces where each element is a pointer to a concrete type.
Here is a snippet how you would do this.
var x int
var s string
data := []interface{}{&x, &s}
rows.Scan(data...)
Note on the use of the ... spread operator.
Here are some related questions that will explain a bit more:
golang: slice of struct != slice of interface it implements?
Cannot convert []string to []interface {}
If you really want to pass a []*interface{} (perhaps you don't know the concrete types of the output) you must first wrap each *interface{} in a interface{}:
values := make([]interface{}, columnsCount)
for i := range values {
values[i] = new(interface{})
}
Individual values passed into a ...interface{} parameter are automatically wrapped in a interface{}, but just like []int... won't satisfy ...interface{}, neither will []*interface{}....
I have an interface{} variable and I know it's a pointer to slice:
func isPointerToSlice(val interface{}) bool {
value := reflect.ValueOf(val)
return value.Kind() == reflect.Ptr && value.Elem().Kind() == reflect.Slice
}
But I'm finding difficult to type cast it into an []interface{} variable:
if isPointerToSlice(val) {
slice, worked := reflect.ValueOf(val).Elem().Interface().([]interface{})
// 'worked' is false :(
}
This doesn't work. Any idea how can I solve this?
If you just want to convert a slice to []interface{} you can use something like this:
func sliceToIfaceSlice(val interface{}) []interface{} {
rf := reflect.Indirect(reflect.ValueOf(val)) // skip the pointer
if k := rf.Kind(); k != reflect.Slice && k != reflect.Array {
// panic("expected a slice or array")
return nil
}
out := make([]interface{}, rf.Len())
for i := range out {
out[i] = rf.Index(i).Interface()
}
return out
}
playground
You can simply use type assertion to obtain the value stored in an interface, e.g.
if isPointerToSlice(val) {
var result []interface{}
result = *val.(*[]interface{})
fmt.Println(result)
} else {
fmt.Println("Not *[]interface{}")
}
The type of the value stored in the interface as you claim is pointer to []interface{}, which is *[]interface{}. The result of the type assertion will be a pointer, just dereference it to get the slice []interface{}.
Using short variable declaration:
result := *val.(*[]interface{}) // type of result is []interface{}
Try it on the Go Playground.
Also your attempt also works:
slice, worked := reflect.ValueOf(val).Elem().Interface().([]interface{})
fmt.Println(slice, worked)
Here's the edited the Playground example which proves your solution works.
But using reflection is unnecessary (as it can be done with type assertion).
Also note that *[]interface{} and *[]someOtherType are 2 different types and you can't obtain a value of *[]interface{} if there is something else in val.
Icza's answer is great and will work especially if you can't know for sure you are getting an interface slice, however if you don't want to bother with the reflect package at all and want to keep imported code low, you can use type switching to obtain the same functionality using only built-in methods.
Using this method, you can shorten your code to just:
package main
import (
"fmt"
)
func main() {
s := []interface{}{"one", 2}
p := &s
do(p)
}
func do(val interface{}) {
switch val.(type){
case *[]interface{}:
var result []interface{}
result = *val.(*[]interface{})
fmt.Println(result)
}
}
Playground: http://play.golang.org/p/DT_hb8JcVt
The downside is if you don't know the exact type of slice you are receiving beforehand, then this will not work unless you list all possible types for handling and assertion.
Is it possible to use slices as keys?
There is my attempt:
h := map[[]string]string{
[]string{"a", "b"} : "ab",
}
the compiler gives me an error invalid map key type []string. So either it's not possible or I declared it incorrectly (if so, what would be a correct way?).
However, it is possible to use arrays as map keys:
package main
import "fmt"
func main() {
m := make(map[[2]int]bool)
m[[2]int{1, 2}] = false
fmt.Printf("%v", m)
}
No, slices cannot be used as map keys as they have no equality defined.
Volker already told that this is not possible and I will give a little bit more details of why is it so with examples from the spec.
Map spec tells you:
The comparison operators == and != must be fully defined for operands
of the key type; thus the key type must not be a function, map, or
slice.
It already tells you that the slice can't be a key, but you could have checked it also in the comparison spec:
Slice, map, and function values are not comparable.
This means that also slice can't be a key, an array can be a key. For example you can write:
h := map[[2]string]string{
[2]string{"a", "b"} : "ab",
}
Depending on your requirements and the complexity of your data, you could use a string as a map key and then use a hash of your slice as the map key.
The nice thing is you can use this technique with anything that can be converted to or from a slice of bytes.
Here's a quick way to convert your slice of strings into a slice of bytes:
[]byte(strings.Join([]string{},""))
Here's an example using SHA1:
type ByteSliceMap struct {
buf *bytes.Buffer
m map[string][]byte
}
func (b *ByteSliceMap) key(buf []byte) string {
h := sha1.New()
h.Write(buf)
sum := h.Sum(nil)
return fmt.Sprintf("%x", sum)
}
func (t *ByteSliceMap) value(key []byte) (value []byte, ok bool) {
value, ok = t.m[t.key(key)]
return
}
func (t *ByteSliceMap) add(key, value []byte) {
if t.m == nil {
t.m = make(map[string][]byte)
}
t.m[t.key(key)] = value
}
Working version
One way to get around this problem is to actually create a key from a slice which has well defined comparison operators:
func createKey(s []string) string { return fmt.Sprintf("%q", s) }
m := make(map[string]string)
s := []string{"a","b"}
m[createKey(s)] = "myValue"
In a similar fashion you would have to create functions for creating keys of slices with type different to string.