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.
Related
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 ®ister.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
I have a slice of structs that looks like:
type KeyValue struct {
Key uint32
Value uint32
}
var mySlice []Keyvalue
This slice mySlice can have a variable length.
I would like to pass all elements of this slice into a function with this signature:
takeKeyValues(keyValue []uint32)
Now I could easily allocate a slice of []uint32, populate it with all the keys/values of the elements in mySlice and then pass that slice as an argument into takeKeyValues()...
But I'm trying to find a way of doing that without any heap allocations, by directly passing all the keys/values on the stack. Is there some syntax trick which allows me to do that?
There is no safe way to arbitrarily reinterpret the memory layout of the your data. It's up to you whether the performance gain is worth the use of an unsafe type conversion.
Since the fields of KeyValue are of equal size and the struct has no padding, you can convert the underlying array of KeyValue elements to an array of uint32.
takeKeyValues((*[1 << 30]uint32)(unsafe.Pointer(&s[0]))[:len(s)*2])
https://play.golang.org/p/Jjkv9pdFITu
As an alternative to JimB's answer, you can also use the reflect (reflect.SliceHeader) and unsafe (unsafe.Pointer) packages to achieve this.
https://play.golang.org/p/RLrMgoWgI7t
s := []KeyValue{{0, 100}, {1, 101}, {2, 102}, {3, 103}}
var data []uint32
sh := (*reflect.SliceHeader)(unsafe.Pointer(&data))
sh.Data = uintptr(unsafe.Pointer(&s[0]))
sh.Len = len(s) * 2
sh.Cap = sh.Len
fmt.Println(data)
I a bit puzzled by what you want. If the slice is dynamic, you have to grow it dynamically as you add elements to it (at the call site).
Go does not have alloca(3), but I may propose another approach:
Come up with an upper limit of the elements you'd need.
Declare variable of the array type of that size (not a slice).
"Patch" as many elements you want (starting at index 0) in that array.
"Slice" the array and pass the slice to the callee.
Slicing an array does not copy memory — it just takes the address of the array's first element.
Something like this:
func caller(actualSize int) {
const MaxLen = 42
if actualSize > MaxLen {
panic("actualSize > MaxLen")
}
var kv [MaxLen]KeyValue
for i := 0; i < actualSize; i++ {
kv[i].Key, kv[i].Value = 100, 200
}
callee(kv[:actualSize])
}
func callee(kv []KeyValue) {
// ...
}
But note that when the Go compiler sees var kv [MaxLen]KeyValue, it does not have to allocate it on the stack. Basically, I beleive the language spec does not tell anything about the stack vs heap.
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)
}
I'm writing a test that a JSON list is empty.
{"matches": []}
The object has type map[string]interface{}, and I want to test that the list is empty.
var matches := response["matches"]
if len(matches) != 0 {
t.Errorf("Non-empty match list!")
}
However I'm told at compile time that this is invalid
invalid argument matches (type interface {}) for len
If I try casting to a list type:
matches := response["matches"].([]string)
I get a panic:
panic: interface conversion: interface is []interface {}, not []string [recovered]
What do I want to write here?
JSON parsing with maps in Go uses interfaces everywhere. Imagine you have the following JSON object:
{
"stuff" : [
"stuff1",
"stuff2",
"stuff3",
]
}
The Go JSON library will parse the outer object as a map from keys to values, as you've seen in your code. It maps variable names as keys to the values that correspond to those variable names. However, since it has no way of knowing ahead of time what those values are, the value type of the map is simply interface{}. So let's say you know there's a key called "stuff", and you know that its value is an array. You could do:
arr := myMap["stuff"]
And you know that it's an array type, so you can actually instead do:
arr := myMap["stuff"].([]interface{})
the problem here is that while you're right that it's an array, and the JSON library knows this, it has no way of knowing that every element will be of type string, so there's no way for it to decide that the array type should actually be []string. Imagine if you had done this instead:
{
"stuff" : [
"stuff1",
"stuff2",
3
]
}
Well "stuff" can't now be an array of strings because one of the elements isn't a string. In fact, it can't be an array of anything - there's no single type that would satisfy the types of all of the elements. So that's why the Go JSON library has no choice but to leave it as []interface{}. Luckily, since all you want is the length, you're already done. You can just do:
arr := myMap["stuff"].([]interface{})
l := len(arr)
Now that's all fine and good, but let's say that down the road you want to actually look at one of the elements. You could now take out an element and, knowing that it's a string, do:
arr := myMap["stuff"].([]interface{})
iv := arr[0] // interface value
sv := iv.(string) // string value
NOTE
When I say "array," I mean array in the JSON sense - these are JSON arrays. The data structure that represents them in Go is called a "slice" (Go has arrays too, but they're a separate thing - if you're used to arrays in languages like C or Java, Go slices are the closest analogue).
When dealing with JSON, you can add type declarations for array and object, then add methods as needed to help with conversion:
package main
import "encoding/json"
type (
array []interface{}
object map[string]interface{}
)
func (o object) a(s string) array {
return o[s].([]interface{})
}
func main() {
data := []byte(`{"matches": []}`)
var response object
json.Unmarshal(data, &response)
matches := response.a("matches")
mLen := len(matches)
println(mLen == 0)
}
https://golang.org/ref/spec#Type_declarations
example code (edited code snippet): http://play.golang.org/p/eZV4WL-4N_
Why is it that
for x, _ := range body.Personality {
body.Personality[x].Mutate()
}
successfully mutates the structs' contents, but
for _, pf := range body.Personality{
pf.Mutate()
}
does not?
Is it that range creates new instances of each item it iterates over? because the struct does in fact mutate but it doesn't persist.
The range keyword copies the results of the array, thus making it impossible to alter the
contents using the value of range. You have to use the index or a slice of pointers instead of values
if you want to alter the original array/slice.
This behaviour is covered by the spec as stated here. The crux is that an assignment line
x := a[i] copies the value a[i] to x as it is no pointer. Since range is defined to use
a[i], the values are copied.
Your second loop is roughly equivalent to:
for x := range body.Personality {
pf := body.Personality[x]
pf.Mutate()
}
Since body.Personality is an array of structs, the assignment to pf makes a copy of the struct, and that is what we call Mutate() on.
If you want to range over your array in the way you do in the example, one option would be to make it an array of pointers to structs (i.e. []*PFile). That way the assignment in the loop will just take a pointer to the struct allowing you to modify it.