Is it possibile to obtain a reference to an Interface Value without
reccurring to reflection? If not, why not?
I have attempted:
package foo
type Foo struct {
a, b int
}
func f(x interface{}) {
var foo *Foo = &x.(Foo)
foo.a = 2
}
func g(foo Foo) {
f(foo)
}
but it fails with:
./test.go:8: cannot take the address of x.(Foo)
To clear your doubts if you go by the meaning Assert
state a fact or belief confidently and forcefully
in your example x.(Foo) is just a type assertion it's not a object so you can not get its address.
so at runtime when the object will be created for example
var c interface{} = 5
d := c.(int)
fmt.Println("Hello", c, d) // Hello 5 5
it only assert that
asserts that c is not nil and that the value stored in c is of type int
So its not any physical entity in memory but at runtime d will be allocated memory based on asserted type and than the contents of c will be copied into that location.
So you can do something like
var c interface{} = 5
d := &c
fmt.Println("Hello", (*d).(int)) // hello 5
Hope i cleared your confusion.
Related
I have been trying to figure out why one particular line will compile, while another won't.. Here's a distilled version:
type A *string
type B *string
func TakeStringPointer(a *string) {
fmt.Println("something: %s\n", *a)
}
func TakeA(a A) {
fmt.Println("something else: %s\n", *a)
}
func Sample() {
aa := "asdf"
var pA A
var pB B
var pString *string
pA = &aa
pB = &aa
pString = &aa
TakeStringPointer(pString)
TakeStringPointer(pA)
TakeStringPointer(pB)
TakeA(pA)
TakeA(pB) // Does not compile
TakeA(pString) // Does compile
}
as far as I understand it, TakeA(pB) and TakeA(pString) should either both work, or both not work...
A value x is assignable to a variable of type T if:
x’s type is identical to T.
x’s type V and T have identical underlying types…
is in the go spec. For me, I would expect both to compile, as both A and B have identical underlying types. (Or, neither would, as *string is not the same thing as A, since we have a type declaration).
What's going on here?
x’s type V and T have identical underlying types…
You quoted the spec and elided the important part. In full, that part of the spec reads:
x's type V and T have identical underlying types and at least one of V or T is not a defined type.
What you have is not a type alias, it is a defined type. (Type aliases are of the form type A = B.) Therefore a function that takes the defined type B cannot take the defined type A; it can take B, or it can take B's underlying type.
If I have a struct type A which is used as a pointer (has pointer receivers only, the constructor returns *A, etc.), what is the difference between embedding a struct type B as B versus *B?
That is, what is the difference between
type B struct {...}
type A struct {
B
// ...
}
and
type B struct {...}
type A struct {
*B
// ...
}
For example, is there ever copying of the embedded field?
Edit: I should also mention that the embedded struct B only has pointer receivers.
The zero values of the two structures are different, which can be a significant ergonomic difference.
Consider an embedded type
type B struct {
X int
}
func (b *B) Print() { fmt.Printf("%d\n", b.X) }
If we embed this directly as an object
type AObj struct {
B
}
then the zero value of type AObj includes an embedded object of type B, which also has its zero value, and therefore we can safely
var aObj AObj
aObj.Print() // prints 0
But if we instead embed a pointer
type APtr struct {
*B
}
the zero value of this struct has a nil pointer value, and we can't really use it directly.
var aPtr APtr
aPtr.Print() // panics
Objects get copied in hopefully the way you might expect. If you create a new AObj object, it gets a copy of the embedded B.
aObj2 := aObj
aObj.X = 1
aObj2.Print() // prints 0, because it has a copy
If you create a new APtr object, it gets a copy of the *B, which means it shares the underlying concrete object.
aPtr.B = &B{}
aPtr2 := aPtr
aPtr.X = 1
aPtr2.Print() // prints 1, because both objects point at the same B
Runnable example at https://play.golang.org/p/XmOgegwVFeE
Consider a simple example program. A structAPtr embeds a pointer, a structAVal embeds a struct structB directly:
package main
import "fmt"
type structB struct {
foo int
}
type structAPtr struct {
bar *structB
}
type structAVal struct {
bar structB
}
func main() {
// referencing bStruct
b1 := structB{foo: 12}
aPtr := structAPtr{bar: &b1}
fmt.Println("Before assignment:")
fmt.Printf("aPtr.bar.foo = %d, b.foo = %d\n", aPtr.bar.foo, b1.foo)
aPtr.bar.foo = 42
fmt.Println("After assignment:")
fmt.Printf("aPtr.bar.foo = %d, b.foo = %d\n", aPtr.bar.foo, b1.foo)
// copying bStruct
b2 := structB{foo: 12}
aVal := structAVal{bar: b2}
fmt.Println("Before assignment:")
fmt.Printf("aVal.bar.foo = %d, b.foo = %d\n", aVal.bar.foo, b2.foo)
aVal.bar.foo = 42
fmt.Println("After assignment:")
fmt.Printf("aVal.bar.foo = %d, b.foo = %d\n", aVal.bar.foo, b2.foo)
}
The int structB.foo is used to demonstrate whether structB changes when manipulated inside of structAPtr or structAVal.
This program outputs:
Before assignment:
aPtr.bar.foo = 12, b.foo = 12
After assignment:
aPtr.bar.foo = 42, b.foo = 42 <------------ both changed
Before assignment:
aVal.bar.foo = 12, b.foo = 12
After assignment:
aVal.bar.foo = 42, b.foo = 12 <------------ only assignee changed
Looking at the result shows:
changing the value of the pointer to structB changes structB
changing the value of the copied version structB in structAVal leaves structB unaffected (it is still 5, even after 42 was assigned to aVal)
Edit:
If your structB has only pointer receivers anyways, the intended behavior is probably such that changing structB in strucA updated both of them. That's scenario 1 in my example and requires a pointer for sure. From A Tour of Go:
Methods with pointer receivers can modify the value to which the receiver points [...]. Since methods often need to modify their receiver, pointer receivers are more common than value receivers.
Hope that helps!
I have some confusion regarding passign slices to function. Here is what I have readed:
Here are what I have understood: slice is a structure with a pointer to real data; when we are passing a slice to a function, we just copy a pointer, but the function is working with the same data as original function.
Here is my code:
type Example struct {
A int
B string
}
func foo(d []Example) {
for _, e := range d {
e.B = "bye"
}
}
func main() {
a := Example{}
a.A = 10
a.B = "hello"
b := Example{}
b.A = 10
b.B = "hello"
var c []Example
c = append(c, a)
c = append(c, b)
foo(c)
for _, e := range c {
fmt.Println(e.B)
}
}
I have passed slice of structs to a function and have changed the struct in the function. Why I have old values in the main function ?
Because it's a slice of structs, not a slice of pointers to structs. When you execute:
for _, e := range d
Inside the loop, e is a copy of the element from the slice; modifying it does not modify what's in the slice. If d were a []*Example, it would work as you expected: https://play.golang.org/p/4ZgLETpq6d0
Note in particular that this has nothing at all to do with slices. If it were:
func foo(d Example) {
d.B = "bye"
}
You would run into the same problem: the function is modifying a copy of the struct, so the caller's copy is unaffected by what happens inside the function.
Another potential solution without using pointers would be to modify the values inside the slice, rather than in a copy of the element:
func foo(d []Example) {
for i := range d {
d[i].B = "bye"
}
}
Working example of this style: https://play.golang.org/p/_UJGU0XqaUO
With a type:
type A struct {
B int, C *int
}
How do I initialise a pointer member to a non-zero value inline, without creating temporaries?
a := A{
B: 42,
C: ?,
}
For the specific example you've given you are limited in what you can do without introducing additional statements.
If you want C to point at an initialised integer variable, you will need an additional statement to define that variable since you can't take the address of an integer literal (i.e. &42 would be an error).
If you just want to initialise C as a pointer to a new zero value, you are in luck though and can set it to new(int).
If you were instead dealing with a different type that had an initialiser syntax, you would also been in luck. For example, if C was a pointer to a structure, you could initialise it to &TheStruct{...}.
If none of these are appropriate, and you are really only after code clarity for initialising *int variables, a helper function might fit your requirements. For example:
func makeIntPointer(v int) *int {
return &v
}
package main
import "fmt"
type A struct {
B int
C *int
}
func newint(i int) *int{
return &i
}
func main() {
c := newint(5)
a := &A{
B: 42,
C: c,
}
fmt.Printf(" %v" , *a.C)
fmt.Printf(" %#v" , a.C)
}
http://play.golang.org/p/s0HIMHoMRo
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.