I'm confused as to why line 15 is not valid. Why can't a pointer to a big.Int be dereferenced, whilst a pointer to an int can?
package main
import (
"fmt"
"big"
)
func main() {
var c *int = getPtr()
fmt.Println(c)
fmt.Println(*c)
var d *big.Int = big.NewInt(int64(0))
fmt.Println(d)
// does not compile - implicit assignment of big.Int
// field 'neg' in function argument
//fmt.Println(*d)
}
func getPtr() *int {
var a int = 0
var b *int = &a
return b
}
It's because Int is a struct with unexported fields. When you pass a struct by value to a function, you're making a copy of it. The Go spec states that for this to be legal
...either all fields of T must be
exported, or the assignment must be in
the same package in which T is
declared. In other words, a struct
value can be assigned to a struct
variable only if every field of the
struct may be legally assigned
individually by the program.
Related
So I have some interfaces and structs:
type Component interface{}
type Position struct{
x float64
}
func Main(){
var components []Components
components = append(components, &Position{1.0})
pos := components[0] // this is a Component, however reflect.TypeOf() returns *Position
*pos = Position{2.0} // this won't compile as golang says you can't dereference a 'Component'
}
How would I modify the actual value (e.g. change 'x') inside the pos variable one I retrieved it? I am storing these pointers in a Component slice as there are various types that implement components.
I have tried doing this:
func Swap(component *Component, value Component){
*component = value
}
however this does not work (it runs however the new value is not udpated). How do I dereference the component and assign its value?
You should use type assertions:
package main
import (
"fmt"
)
type Component interface{}
type Position struct {
x float64
}
func (p Position) String() string {
return fmt.Sprintf("%f", p.x)
}
func main() {
components := []Component{&Position{1.0}}
fmt.Println(components)
pos, ok := components[0].(*Position)
if !ok {
panic("Not a *Position")
}
pos.x = 1000.0
fmt.Println(components)
}
This prints:
[1.000000]
[1000.000000]
If you need to check for multiple types, you could use a type switch.
When checking the reflect.Kind() of a slice, reflect correctly identifies it as a slice when not stored inside a pointer:
package main
import (
"fmt"
"reflect"
)
type Dog struct {
Name string
Age int
}
func main() {
var dogs []Dog
rDogs := reflect.ValueOf(dogs)
fmt.Println(rDogs.Kind())
}
Output:
slice
However, when a slice is stored inside a pointer, reflect.Kind() identifies it as a struct:
package main
import (
"fmt"
"reflect"
)
type Dog struct {
Name string
Age int
}
func main() {
dogs1 := make([]Dog, 0)
pointer := &dogs1
printPointerValueKind(pointer)
var dogs2 []Dog
pointer = &dogs2
printPointerValueKind(pointer)
}
func printPointerValueKind(pointer interface{}) {
if pointer != nil {
rPointer := reflect.ValueOf(pointer)
if rPointer.Kind() == reflect.Ptr {
value := rPointer.Elem()
rValue := reflect.ValueOf(value)
fmt.Println(rValue.Kind())
}
}
}
Output:
struct
struct
My questions are:
Why does this happen?
Is there a way to store a slice inside a pointer and still have reflect.Kind() identify it as a slice?
1. (reflect.Value).Elem() returns a reflect.Value, which is a struct, and which does not need to be passed to reflect.ValueOf again if you're looking for the kind of the type that the value holds.
2. rPointer.Elem().Kind() should be enough for what you need.
For example
var myStructRef *Vertex
var myStruct Vertex
myStructRef = &Vertex{2, 3}
myStruct = Vertex{2, 3}
fmt.Println(myStructRef)
fmt.Println(myStruct)
changeByReferenceStruct(myStructRef)
changeByValueStruct(myStruct)
fmt.Println(myStructRef)
fmt.Println(myStruct)
And
func changeByValueStruct(myStruct Vertex) {
myStruct.X = 5
fmt.Println(myStruct)
}
func changeByReferenceStruct(myStruct *Vertex) {
myStruct.X = 7
fmt.Println(myStruct)
}
Isn't both myStructRef *Vertex and myStruct Vertex a pointer pointing to the struct itself? Why is there a discrepancy in behavior when I modify the struct in a function?
Is golang creating a new struct in changeByValueStruct when it resolves the parameter?
When you pass a pointer as an argument, what happens under the hood is that a copy of that pointer is created and passed to the underlying function. It should not be confused with pass-by-reference.
Let's look at an example to better grasp it:
package main
import (
"fmt"
)
type Point struct {
x int
y int
}
func (p Point) String() string {
return fmt.Sprintf("(%d, %d)", p.x, p.y)
}
func modifyValue(point Point) {
point.x += 10
}
func modifyPointer(point *Point) {
point.x = 5
point.y = 5
}
func modifyReference(point *Point) {
point = &Point{5, 5}
}
func main() {
p := Point{0, 0}
fmt.Println(p) // prints (0, 0)
modifyValue(p)
fmt.Println(p) // prints (0, 0)
modifyPointer(&p)
fmt.Println(p) // prints (5, 5)
p = Point{0, 0}
modifyReference(&p)
fmt.Println(p) // prints (0, 0)
}
What happens inside the modifyValue function is that a totally different instance of a Point structure is modified, so the value passed when calling the function is unaffected.
In the second example, a pointer to the structure is passed so the fields of the structure can be modified in a way that is visible from outside.
The most interesting point is made by the last function, modifyReference. If you are familiar with the pass by reference paradigm available in other languages you would expect to be able to modify the referenced object altogether, but this doesn't happen. It's because you're modifying a copy of the pointer passed as argument.
You may wonder, if everything is passed by value, when should you pass pointers and when values. Passing values assures the caller function that the passed structure cannot suffer any changes, so when you need this behaviour, go for the value. The downside of this is that a copy of the entire object is made and, if it is too big, memory becomes a concern.
If you're passing a big structure as an argument, using a pointer is better because it saves space, but you lose the guarantee that the object won't suffer any changes.
Passing struct to function argument makes copy of values. And passing pointer of struct doesn't. So passing struct can't update field value.
package main
import (
"fmt"
)
type Foo struct {
value int
}
func PassStruct(foo Foo) {
foo.value = 1
}
func PassStructPointer(foo *Foo) {
foo.value = 1
}
func main() {
var foo Foo
fmt.Printf("before PassStruct: %v\n", foo.value)
PassStruct(foo)
fmt.Printf("after PassStruct: %v\n", foo.value)
fmt.Printf("before PassStructPointer: %v\n", foo.value)
PassStructPointer(&foo)
fmt.Printf("after PassStructPointer: %v\n", foo.value)
}
https://play.golang.org/p/AM__JwyaJa
Please check the below program. Var z is of type interface{}. It stores the type of struct X. But I cannot use it to create a new instance of X. I have some requirement where I need to keep the type of the object in an interface{} variable, and use that to create an instance of that type. Here is a link for the snippet on go playground
package main
import (
"fmt"
"reflect"
)
type X struct {
a int
b int
}
type MyInt int
func main() {
x := X{}
y := reflect.TypeOf(x)
fmt.Printf("%v\n", reflect.New(y))
var z interface{}
z = y
fmt.Printf("%v\n", z) // prints main.X
//Below line throws the error
fmt.Printf("%v\n", reflect.New(z)) //----> This line throws error
}
You can use type assertion to extract the reflect.Type value from an interface{} value:
fmt.Printf("%v\n", reflect.New(z.(reflect.Type))) //----> Works!
Your modified example on the Go Playground.
Note that the above example panics if z does not hold a value of type reflect.Type or if it is nil. You can use the special comma-ok form to prevent that:
if t, ok := z.(reflect.Type); ok {
fmt.Printf("%v\n", reflect.New(t)) // t is of type reflect.Type
} else {
fmt.Println("Not the expected type or nil!")
}
The example below shows what happens when you reflect on an interface {} that is set to an object (g) and a pointer to said object (h). Is this by design, should I expect that my datatype is lost or rather or that I cannot get name of the datatype back when I put my pointer in an interface {}?
package main
import "fmt"
import "reflect"
type Foo struct {
Bar string
}
func main() {
f := Foo{Bar: "FooBar"}
typeName := reflect.TypeOf(f).Name()
fmt.Printf("typeName %v\n", typeName)
var g interface{}
g = f
typeName = reflect.TypeOf(g).Name()
fmt.Printf("typeName %v\n", typeName)
var h interface{}
h = &f
typeName = reflect.TypeOf(h).Name()
fmt.Printf("typeName %v\n", typeName)
}
Outputs:
typeName Foo
typeName Foo
typeName
Also at:
http://play.golang.org/p/2QuBoDxHfX
As the Name method's documentation says, unnamed types will return an empty string:
Name returns the type's name within its package.
It returns an empty string for unnamed types.
The type of h is an unnamed pointer type whose element type is the named struct type Foo:
v := reflect.TypeOf(h)
fmt.Println(v.Elem().Name()) // prints "Foo"
If you want an identifier for complex unnamed types like this, use the String method:
fmt.Println(v.String()) // prints "*main.Foo"