Golang how to create map to pointer to slice using make - go

I want to create a dynamically initialized bitmap data structure. I'm trying to use the golang maps for this:
type Register map[bool]*[]bool
The way I'm initializing the map is:
register := make(Register)
register[true] := make(*[]bool, len(arr)) // arr is the array for which i want to create the bitmap
This obviously creates compilation issue with the error:
error: cannot make type *[]bool
I have also tried using the pointer syntax:
register[true] = &(make([]bool, len(arr)))
Which gives me the error:
cannot take the address of make([]bool, len(arr))
The reason I want the map values to be *[]bool is so that the write back to the map stays sane and in-place.
While go doesn't complain about map[bool]*[]bool hence its a valid type.
If it is valid the what is the idomatic way to use it in the fashion I want to. If not then what would be the alternate way?

Use the following code to create a pointer to a slice:
register := make(Register)
s := make([]bool, len(arr)) // create addressable slice value s.
register[true] = &s
You can use new to eliminate the variable declaration, but this approach does not reduce the number of lines of code and it adds another map index operation.
register := make(Register)
register[true] = new([]bool)
*register[true] = make([]bool, len(arr))
Declare a function to move the assignment on to a single line:
func makeSlice(n int) *[]bool {
s := make([]bool, len(arr))
return &s
}
...
register := Register{true: makeSlice(len(arr))}
Because the map keys have two possible values, true and false, you might be able to simplify the code by using a struct instead of a map:
type Register struct {
t, f []bool
}
register := Register{t: make([]bool, len(arr))}
The struct fields in register are addressable, so you can use &register.t to get the *[]bool.
A variation on this theme is to use an array:
type Register [2][]bool
register := Register{1: make([]bool, len(arr))}
If you modify the slice elements only and not the slice value, then there's no need to use a pointer to the slice.
type Register map[bool][]bool
register := make(Register)
register[true] := make([]bool, len(arr))
If you do modify the slice value, the map[bool][]bool may be more efficient and easier to use. The application will need to assign back to the map when the slice value is modified, but you eliminate the indirections.

Another option is using the new function:
package main
import "fmt"
func main() {
type Register map[bool]*[]bool
register := make(Register)
register[true] = new([]bool)
// main.Register{true:(*[]bool)(0xc000004078)}
fmt.Printf("%#v\n", register)
}
https://golang.org/pkg/builtin#new

Related

Generic function which appends two arrays

Not able to figure out how to convert interface{} returned from function into an array of structs
As part of some practise i was trying to create a function which can take 2 slices of some type and concatenates both and returns the slice.
The code can be found here - https://play.golang.org/p/P9pfrf_qTS1
type mystruct struct {
name string
value string
}
func appendarr(array1 interface{}, array2 interface{}) interface{} {
p := reflect.ValueOf(array1)
q := reflect.ValueOf(array2)
r := reflect.AppendSlice(p, q)
return reflect.ValueOf(r).Interface()
}
func main() {
fmt.Println("=======")
array1 := []mystruct{
mystruct{"a1n1", "a1v1"},
mystruct{"a1n2", "a1v2"},
}
array2 := []mystruct{
mystruct{"a2n1", "a2v1"},
mystruct{"a2n2", "a2v2"},
}
arrayOp := appendarr(array1, array2)
fmt.Printf("arr: %#v\n", arrayOp) // this shows all the elements from array1 and 2
val := reflect.ValueOf(arrayOp)
fmt.Println(val) // output is <[]main.mystruct Value>
fmt.Println(val.Interface().([]mystruct)) // exception - interface {} is reflect.Value, not []main.mystruct
}
I may have slices of different types of structs. I want to concatenate them and access the elements individually.
If there is any other way of achieving the same, please do let me know.
reflect.Append() returns a value of type reflect.Value, so you don't have to (you shouldn't) pass that to reflect.ValueOf().
So simply change the return statement to:
return r.Interface()
With this it works and outputs (try it on the Go Playground):
=======
arr: []main.mystruct{main.mystruct{name:"a1n1", value:"a1v1"}, main.mystruct{name:"a1n2", value:"a1v2"}, main.mystruct{name:"a2n1", value:"a2v1"}, main.mystruct{name:"a2n2", value:"a2v2"}}
[{a1n1 a1v1} {a1n2 a1v2} {a2n1 a2v1} {a2n2 a2v2}]
[{a1n1 a1v1} {a1n2 a1v2} {a2n1 a2v1} {a2n2 a2v2}]
You also don't need to do any reflection-kungfu on the result: it's your slice wrapped in interface{}. Wrapping it in reflect.Value and calling Value.Interface() on it is just a redundant cycle. You may simply do:
arrayOp.([]mystruct)
On a side note: you shouldn't create a "generic" append() function that uses reflection under the hood, as this functionality is available as a built-in function append(). The builtin function is generic, it gets help from the compiler so it provides the generic nature at compile-time. Whatever you come up with using reflection will be slower.

How to Make array of elements with type specified at run time

I am trying to create a array of elements with a type known only at the run time (a pkg API gets to retrieve elements in json and convert to struct). I have a helper function something like below, which takes an interface as a param and trying to get the type of interface while calling make.
golang compiler doesn't seems to like it.
var whatAmI = func(i interface{}) {
a := reflect.TypeOf(i)
//var typ reflect.Type = a
b := make (a, 10) //10 elem with type of i
//b := new (typ)
fmt.Printf ("a: %v b: %v", a, b)
}
prog.go:21:14: a is not a type
I tried various combinations of reflects but no help so far.
This seems to me can be a common problem to run in to. How can I solve/workaround this?
Get the type for a slice given a value of the element type, v:
sliceType := reflect.SliceOf(reflect.TypeOf(v))
Create a slice with length and capacity (both 10 here).
slice:= reflect.MakeSlice(sliceType, 10, 10)
Depending on what you are doing, you may want to get the actual slice value by calling Interface() on the reflect.Value:
s := slice.Interface()
Run it on the playground.
Just make like :
b := make([]interface{}, 10)
for i := range b {
b[i] = reflect.Zero(a)
}

get underlying type from a specific interface in golang

As the example, can I get a zero value of its underlying type from the interface Work?
func MakeSomething(w Worker){
w.Work()
//can I get a zeor value type of The type underlying w?
//I tried as followed, but failed
copy :=w
v := reflect.ValueOf(&copy)
fm :=v.Elem()
modified :=reflect.Zero(fm.Type())//fm.type is Worker, and modified comes to be nil
fm.Set(modified)
fmt.Println(copy)
}
type Worker interface {
Work()
}
the playground
Since w contains a pointer to a Worker, you might want to get a zero value of the element it is pointing to. Once you get the element, you can create a zero value of its type:
v := reflect.ValueOf(w).Elem() // Get the element pointed to
zero := reflect.Zero(v.Type()) // Create the zero value
Above code snippet will panic if you pass in a non-pointer to MakeSomething. To prevent this, you might want to do the following instead:
v := reflect.ValueOf(w)
if reflect.TypeOf(w).Kind() == reflect.Ptr {
v = v.Elem()
}
zero := reflect.Zero(v.Type())
If you actually want to have a pointer to a new Worker, you just replace reflect.Zero(v.Type()) with reflect.New(v.Type()).

range over addressess of struct array

I have a struct array of type []Struct. When I range over it in the form:
for i, val := range mystructarray
I understand that val is a local variable which contains a copy of mystructarray[i]. Is there a better way of iterating through the addressess of mystructarray than this:
for i := range mystructarray{
valptr = &mystructarray[i]
}
?
There is no way to iterate while receiving a pointer to the contents of the slice (unless of course, it is a slice of pointers).
Your example is the best way:
for i := range mySlice {
x = &mySlice[i]
// do something with x
}
Remember however, if your structs aren't very large, and you don't need to operate on them via a pointer, it may be faster to copy the struct, and provide you with clearer code.

Golang : interface to swap two numbers

I want to swap two numbers using interface but the interface concept is so confusing to me.
http://play.golang.org/p/qhwyxMRj-c
This is the code and playground. How do I use interface and swap two input numbers? Do I need to define two structures?
type num struct {
value interface{}
}
type numbers struct {
b *num
c *num
}
func (a *num) SwapNum(var1, var2 interface{}) {
var a num
temp := var1
var1 = var2
var2 = temp
}
func main() {
a := 1
b := 2
c := 3.5
d := 5.5
SwapNum(a, b)
fmt.Println(a, b) // 2 1
SwapNum(c, d)
fmt.Println(c, d) // 5.5 3.5
}
First of all, the interface{} type is simply a type which accepts all values as it is an interface with an empty method set and every type can satisfy that. int for example does not have any methods, neither does interface{}.
For a method which swaps the values of two variables you first need to make sure these variables are actually modifiable. Values passed to a function are always copied (except reference types like slices and maps but that is not our concern at the moment). You can achieve modifiable parameter by using a pointer to the variable.
So with that knowledge you can go on and define SwapNum like this:
func SwapNum(a interface{}, b interface{})
Now SwapNum is a function that accepts two parameters of any type.
You can't write
func SwapNum(a *interface{}, b *interface{})
as this would only accept parameters of type *interface{} and not just any type.
(Try it for yourself here).
So we have a signature, the only thing left is swapping the values.
func SwapNum(a interface{}, b interface{}) {
*a, *b = *b, *a
}
No, this will not work that way. By using interface{} we must do runtime type assertions to check whether we're doing the right thing or not. So the code must be expanded using the reflect package. This article might get you started if you don't know about reflection.
Basically we will need this function:
func SwapNum(a interface{}, b interface{}) {
ra := reflect.ValueOf(a).Elem()
rb := reflect.ValueOf(b).Elem()
tmp := ra.Interface()
ra.Set(rb)
rb.Set(reflect.ValueOf(tmp))
}
This code makes a reflection of a and b using reflect.ValueOf() so that we can
inspect it. In the same line we're assuming that we've got pointer values and dereference
them by calling .Elem() on them.
This basically translates to ra := *a and rb := *b.
After that, we're making a copy of *a by requesting the value using .Interface()
and assigning it (effectively making a copy).
Finally, we set the value of a to b with [ra.Set(rb)]5, which translates to *a = *b
and then assigning b to a, which we stored in the temp. variable before. For this,
we need to convert tmp back to a reflection of itself so that rb.Set() can be used
(it takes a reflect.Value as parameter).
Can we do better?
Yes! We can make the code more type safe, or better, make the definition of Swap type safe
by using reflect.MakeFunc. In the doc (follow the link) is an example which is very
like what you're trying. Essentially you can fill a function prototype with content
by using reflection. As you supplied the prototype (the signature) of the function the
compiler can check the types, which it can't when the value is reduced to interface{}.
Example usage:
var intSwap func(*int, *int)
a,b := 1, 0
makeSwap(&intSwap)
intSwap(&a, &b)
// a is now 0, b is now 1
The code behind this:
swap := func(in []reflect.Value) []reflect.Value {
ra := in[0].Elem()
rb := in[1].Elem()
tmp := ra.Interface()
ra.Set(rb)
rb.Set(reflect.ValueOf(tmp))
return nil
}
makeSwap := func(fptr interface{}) {
fn := reflect.ValueOf(fptr).Elem()
v := reflect.MakeFunc(fn.Type(), swap)
fn.Set(v)
}
The code of swap is basically the same as that of SwapNum. makeSwap is the same
as the one used in the docs where it is explained pretty well.
Disclaimer: The code above makes a lot of assumptions about what is given and
what the values look like. Normally you need to check, for example, that the given
values to SwapNum actually are pointer values and so forth. I left that out for
reasons of clarity.

Resources