Is it possible to create a slice from an existing reference? - go

Let's say I have the following function:
func foo(bar []int) {
bar[0] = 456
}
I want to create an []int with one element that references a, such that when I:
var a int = 10
// mySlice := ... crazy hackery?
foo(mySlice)
The value of a will be 456.
I know this is crazy and stupid and not at all the right thing to do. I'm not looking for the "correct" way. The function prototype for foo must remain the same.
I can guarantee that while the underlying int will change, the slice that points to it is immutable.
The reason for the strange requirement is because this is for the c2go project.

You can cast any types you want through an unsafe.Pointer.
First convert the *int to a pointer to an array, then slice it:
(*[1]int)(unsafe.Pointer(&a))[:]
https://play.golang.org/p/bmKcMIj3pb

Related

How []interface{} in Go is implemented?

In Go I can do something like this:
func main() {
var intSlice []interface{}
intSlice = append(intSlice, "hello world")
intSlice = append(intSlice, 1)
for _, v := range intSlice {
fmt.Println(v) // hello world
// 1
}
}
Since a slice is deep down an array, without given a specific type to that array, how can Go know the layout of this array's memory structure? If it's a []string then I know that for every iteration I have to add current address with 4 to get the next item's address, but for an interface{} how can Go knows what to do? I am confused. One possible explain for this is that interface{} is actually a pointer, so []interface{} stores pointers only, the value 1 or "hello world" is stored somewhere outside of the slice. Am I right about this?
An interface is two values: a pointer to the value, and a pointer to the type of the value. So a []interface{} containing all int values is simply an array of interfaces, where each element containing those two values, with each element of the array pointing to the int value, and to its type.

"Cannot use variable of type []struct as []interface" while spreading [duplicate]

This question already has answers here:
slice of struct != slice of interface it implements?
(6 answers)
Closed 10 months ago.
Prototype function
func test(i ...interface{}) {
// Code here
}
Intended use
type foo struct {
// Fields
}
foos := []foo{
// foo1, foo2 ...
}
test(foos...) // ERROR
test(foos[1], foos[2], ...) // OK
Error
cannot use foos (variable of type []foos) as []interface{} value in argument to test
Description
The intended use is to be used like the built-in function append().
https://golang.google.cn/pkg/builtin/#append
func append(slice []Type, elems ...Type) []Type
Although, as I've seen append() doesn't use interface{}, which is strange, since anywhere that I searched all people say to use interface{} when you don't know the type. But they don't.
Nope, append() uses a "build-in" type called Type, which apparently the docs say that it's a int. Although, I cannot use it. There isn't such type. And neither I would know how to use it if there was.
https://golang.google.cn/pkg/builtin/#Type
type Type int
So, I'm very confused here.
Questions
Why does the spread operator not work as intended? For example, in Javascript the spread operator just spreads the array into items. But in Golang it seems like it keeps the same array parameter type as it is but gives the compiler later an instruction to spread it. Which is odd.
Are we even able to make similar custom mechanisms like append() at all? Or am I a dummy and I'm using something wrong anyway?
I think that this is the issue that you are running into here.
https://github.com/golang/go/wiki/InterfaceSlice
I am not an expert in this but have hit this before, the "slice of empty interface" is not an interface and therefore cannot be replaced by any type which is the issue that you are having, it has to do with the memory structure being different. The above has a far better explanation than one that I can give.
You can typecast your typed slice to get what you need:
generic := make([]interface{}, 0)
for _, f := range foos {
generic = append(generic, f)
}
test(generic...) // works
Combining the two non-negative answers into what I feel is the best solution:
interfaceSlice := make([]interface{}, len(foos))
for i, v := range foos {
interfaceSlice[i] = v
}
test(interfaceSlice...)
Partially inspired by:
https://github.com/golang/go/wiki/InterfaceSlice#what-can-i-do-instead

Any one can make sense of connStateInterface?

func (c *conn) setState(nc net.Conn, state ConnState) {
...
c.curState.Store(connStateInterface[state])
...
}
// connStateInterface is an array of the interface{} versions of
// ConnState values, so we can use them in atomic.Values later without
// paying the cost of shoving their integers in an interface{}.
var connStateInterface = [...]interface{}{
StateNew: StateNew,
StateActive: StateActive,
StateIdle: StateIdle,
StateHijacked: StateHijacked,
StateClosed: StateClosed,
}
I can't figure out the trick with connStateInterface, how exactly does it work?
There's a few things going on here...
The [...] declaration creates an actual array instead of a slice, so that indirection is removed. What's being declared here is an array of interface{} types... so you might wonder why the weird map-looking notation?
The StateXXX variables are simply constants declared further above, so they are ints... so the declaration is actually of the form index: value.
Here's a less obfuscated example of that using an array of ints:
var i = [...]int{4: 2, 2: 7}
This will allocate an array containing:
[0, 0, 7, 0, 2]
... note that index 2 has 7, index 4 has 2. Not a common way of declaring an array, but it's valid Go.
So going back to the original declaration, just take the example I gave above, and instead of int, make the array of type interface{}:
var i = [...]interface{}{4: 2, 2: 7}
And you'll get a similar array, but with nil interface values in place of zeroes.
Getting even closer to the original code, the StateXXX constants are just ints, only not literals like in my example.
So, what's the point of all this? Why all the obfuscation?
It's a performance hack. The function c.curState.Store() takes an argument of type interface{}. If you were to pass it an int, the compiled code would have to fumble about with converting the type on each call. A more clear (though obviously impractical) illustration of this might be:
var val interface{}
for i := 0; i < 1000000; i++ {
// the types are different, compiler has to fumble int vs. interface{}
val = i
// do something with val
}
Every time you do val = i a conversion between int and interface{} needs to happen. The code you posted avoids this by creating a static lookup table where all the values are already of type interface.
Therefore, this:
c.curState.Store(connStateInterface[state])
is more efficient than this:
c.curState.Store(state)
Since state would, in this case, need to undergo the int -> interface{} conversion. In the optimized code, state is merely an index looking up a value into an array, the result of which gets you an interface{}... so the int -> interface{} type conversion is avoided.
I'm not familiar with that code, but I'd imagine it's in a critical path and the nanoseconds or whatever savings shaved off likely makes a difference.

What's happening with these pointers?

I wrote some odd code, but I'm not sure why it works and what I can learn from it. I have a slice type build from another struct. I made a function on the slice type to modify itself. To do this, I seem to have to throw around *'s a little much.
I'm trying to learn about pointers in Go and would like a little help. Here's an example (http://play.golang.org/p/roU3MEeT3q):
var ClientNames = []string {"Client A", "Client B", "ClientC"}
type InvoiceSummaries []InvoiceSummary
type InvoiceSummary struct {
Client string
Amt int
}
func (summaries *InvoiceSummaries) BuildFromAbove() {
for _, name := range ClientNames {
*summaries = append(*summaries, InvoiceSummary{name, 100})
}
}
My question is: What is the purpose for each of these * and why am I not using any &?
What is the purpose for each of these * ?
By making the method receiver as pointer, you could easily change the property of the object. I think that's one of the benefit. This example below will prove it.
package main
import "fmt"
type someStruct struct {
someVar int
}
func (s someStruct) changeVal1(newVal int) {
s.someVar = newVal
}
func (s *someStruct) changeVal2(newVal int) {
s.someVar = newVal
}
func main() {
s := someStruct{0}
fmt.Println(s) // {0}
s.changeVal1(3)
fmt.Println(s) // {0}
s.changeVal2(4)
fmt.Println(s) // {4}
(&s).changeVal2(5)
fmt.Println(s) // {5}
}
and why am I not using any &?
Pointer method receiver is quite special, it can also be called from non-pointer struct object. Both of s.changeVal2(4) and (&s).changeVal2(5) are valid & will affect the value of someVar.
Example http://play.golang.org/p/sxCnCD2D6d
You have to use a pointer for the receiver - (summaries *InvoiceSummaries) - because otherwise the argument is passed by value, having a pointer means you pass a reference to the value instead. If not for that, then you couldn't modify the collection at all.
Inside of the methods body you have use * because it is the dereferncing operator and returns the value at the address. Ampersand (&) is the opposite, it gives the address of a value.
Nothing wrong with your code but normally addresses to slices aren't used. A slice is a small struct that gophers are normally happy to pass by value. If a method or function is creating a new slice, the gopher is happy to return the new slice, by value again, as the return value.
Of course passing a slice by value doesn't guarantee anything about the backing store remaining unchanged when the method/function returns. So it can't be used as a way of guaranteeing the data elements of the slice haven't mutated.

Why a slice []struct doesn't behave same as []builtin?

The slices are references to the underlying array. This makes sense and seems to work on builtin/primitive types but why is not working on structs? I assume that even if I update a struct field the reference/address is still the same.
package main
import "fmt"
type My struct {
Name string
}
func main() {
x := []int{1}
update2(x)
fmt.Println(x[0])
update(x)
fmt.Println(x[0])
my := My{Name: ""}
update3([]My{my})
// Why my[0].Name is not "many" ?
fmt.Println(my)
}
func update(x []int) {
x[0] = 999
return
}
func update2(x []int) {
x[0] = 1000
return
}
func update3(x []My) {
x[0].Name = "many"
return
}
To clarify: I'm aware that I could use pointers for both cases. I'm only intrigued why the struct is not updated (unlike the int).
What you do when calling update3 is you pass a new array, containing copies of the value, and you immediately discard the array. This is different from what you do with the primitive, as you keep the array.
There are two approaches here.
1) use an array of pointers instead of an array of values:
You could define update3 like this:
func update3(x []*My) {
x[0].Name = "many"
return
}
and call it using
update3([]*My{&my})
2) write in the array (in the same way you deal with the primitive)
arr := make([]My,1)
arr[0] = My{Name: ""}
update3(arr)
From the GO FAQ:
As in all languages in the C family, everything in Go is passed by
value. That is, a function always gets a copy of the thing being
passed, as if there were an assignment statement assigning the value
to the parameter. For instance, passing an int value to a function
makes a copy of the int, and passing a pointer value makes a copy of
the pointer, but not the data it points to. (See the next section for
a discussion of how this affects method receivers.)
Map and slice values behave like pointers: they are descriptors that
contain pointers to the underlying map or slice data. Copying a map or
slice value doesn't copy the data it points to.
Thus when you pass my you are passing a copy of your struct and the calling code won't see any changes made to that copy.
To have the function change the data in teh struct you have to pass a pointer to the struct.
Your third test is not the same as the first two. Look at this (Playground). In this case, you do not need to use pointers as you are not modifying the slice itself. You are modifying an element of the underlying array. If you wanted to modify the slice, by for instance, appending a new element, you would need to use a pointer to pass the slice by reference. Notice that I changed the prints to display the type as well as the value.

Resources