I have a slice that I want to change (for example i want to remove the first element) using a function. I thought to use a pointer, but I still can't index it. What am I doing wrong?
Playground link:
func change(list *[]int) {
fmt.Println(*list)
*list = *list[1:] //This line screws everything up
}
var list = []int{1, 2, 3}
func main() {
change(&list)
}
You need to use (*list).
func change(list *[]int) {
*list = (*list)[1:]
}
or a different approach that's usually more go idomatic:
func change(list []int) []int {
return list[1:]
}
playground
Related
So basically I was wondering if it possible in GO, because I was playing with Dereference.
For example in Code shown below. Pointer is passed to function and I'm trying to return one letter of passed pointer string, in given example that is H, but however slice can only be used with strings. And I was wondering if it possible to do this using pointer Dereference.
Code Example:
func Test(test *string) {
if len(*test) > 0 {
*test = *test[:1]
}
strings.ToUpper(*test)
}
func main() {
str := "hello"
Test(&str)
fmt.Print( str)
}
Is it possible in Go to pass pointer of string and make it slice of string?
Yes: func (ps *string) []string { return []string{*ps} }
You need to place test in brackets, i.e. dereference the pointer first, and then slice it.
Then the Test function still wouldn't return capital H though, because ToUpper takes and returns a value. So you need to reassign the output of ToUpper to *test as well:
func Test(test *string) {
if len(*test) > 0 {
*test = (*test)[:1] // bracketed `test`
}
*test = strings.ToUpper(*test) // reassign to `test`
}
func main() {
str := "hello"
Test(&str)
fmt.Print(str) // Prints 'H'
}
Go Play example
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
I have a function that has a parameter with the type interface{}. This parameter represents my template data. So on each page it stores different data types (mostly structs). I want to append some data to this parameter's data, but it's an interface{} type and I can't do it.
This is what I tried:
func LoadTemplate(templateData interface) {
appendCustomData(&templateData)
... //other functionality that is not relevant
}
func appendCustomData(dst interface{}) {
// ValueOf to enter reflect-land
dstPtrValue := reflect.ValueOf(dst)
// need the type to create a value
dstPtrType := dstPtrValue.Type()
// *T -> T, crashes if not a ptr
dstType := dstPtrType.Elem()
// the *dst in *dst = zero
dstValue := reflect.Indirect(dstPtrValue)
// the zero in *dst = zero
zeroValue := reflect.Zero(dstType)
// the = in *dst = 0
v := reflect.ValueOf(dst).Elem().Elem().FieldByName("HeaderCSS")
if v.IsValid() {
v = reflect.ValueOf("new header css value")
}
reflect.ValueOf(dst).Elem().Elem().FieldByName("HeaderCSS").Set(reflect.ValueOf(v))
//dstValue.Set(zeroValue)
fmt.Println("new dstValue: ", dstValue)
}
I can successfully get the "HeaderCSS" value. But I can't replace it with another value. What am I doing wrong?
My templateData looks like this:
I have a generic struct:
type TemplateData struct {
FooterJS template.HTML
HeaderJS template.HTML
HeaderCSS template.HTML
//and some more
}
and I have another struct, such as:
type pageStruct struct {
TemplateData //extends the previous struct
Form template.HTML
// and some other maps/string
}
I send this second struct as templateData argument.
Right now I get this error:
"reflect.Value.Set using unaddressable value" at the line: reflect.ValueOf(dst).Elem().Elem().FieldByName("HeaderCSS").Set(reflect.ValueOf(v))
The code from above is inspired from this answer: https://stackoverflow.com/a/26824071/1564840
I want to be able to append/edit values from this interface. Any idea how can I do it? Thanks.
Don't pass a pointer to interface. Instead the interface{} value should contain the pointer. And simply just hand over this interface{} value:
func LoadTemplate(templateData interface) {
appendCustomData(templateData)
... //other functionality that is not relevant
}
Even if you can't use a more concrete type than interface{} (because you must allow multiple types), you can still use type assertion, it will be "super" easy:
func appendCustomData(d interface{}) {
if ps, ok := d.(*pageStruct); ok {
ps.TemplateData.HeaderCSS += "+new"
}
}
Try this one on the Go Playground.
If you must or want to use reflection, this is how appendCustomData() can be implemented:
type Data struct {
Name string
Age int
Marks []int
}
func appendCustomData(d interface{}) {
v := reflect.ValueOf(d).Elem()
if f := v.FieldByName("Name"); f.IsValid() {
f.SetString(f.Interface().(string) + "2")
}
if f := v.FieldByName("Age"); f.IsValid() {
f.SetInt(f.Int() + 2)
}
if f := v.FieldByName("Marks"); f.IsValid() {
f.Set(reflect.ValueOf(append(f.Interface().([]int), 2)))
}
if f := v.FieldByName("Invalid"); f.IsValid() {
f.Set(reflect.ValueOf(append(f.Interface().([]int), 2)))
}
}
Testing it:
d := &Data{
Name: "Bob",
Age: 22,
Marks: []int{5, 4, 3},
}
fmt.Printf("%+v\n", d)
appendCustomData(d)
fmt.Printf("%+v\n", d)
Output (try it on the Go Playground):
&{Name:Bob Age:22 Marks:[5 4 3]}
&{Name:Bob2 Age:24 Marks:[5 4 3 2]}
Update:
To answer your edited question: there is no difference when the value passed is a struct that embeds another struct. But the value wrapped in the interface{} still must be a pointer.
Example appendCustomData() that appends content to pageStruct.TemplateData.HeaderCSS:
func appendCustomData(d interface{}) {
v := reflect.ValueOf(d).Elem()
if f := v.FieldByName("TemplateData"); f.IsValid() {
if f = f.FieldByName("HeaderCSS"); f.IsValid() {
f.Set(reflect.ValueOf(f.Interface().(template.HTML) + "+new"))
}
}
}
Testing it:
ps := &pageStruct{
TemplateData: TemplateData{
HeaderCSS: template.HTML("old"),
},
}
fmt.Printf("%+v\n", ps)
appendCustomData(ps)
fmt.Printf("%+v\n", ps)
Output (try it on the Go Playground):
&{TemplateData:{FooterJS: HeaderJS: HeaderCSS:old} Form:}
&{TemplateData:{FooterJS: HeaderJS: HeaderCSS:old+new} Form:}
This is a very straight forward question.
How do you implement Initialize() below with reflect?
Or is this possible?
func Initialize(v interface{}) {
// ... some reflection code
}
type MyType struct {
Name string
}
func main() {
var val *MyType
// val is nil before initialize
Initialize(val)
// val is now &MyType{Name: ""}
// ...
}
```
Here's how to do it:
func Initialize(v interface{}) {
rv := reflect.ValueOf(v).Elem()
rv.Set(reflect.New(rv.Type().Elem()))
}
This function must be called with a pointer to the value to set:
Initialize(&val)
playground example
The code in this answer panics if the argument type is not a pointer to a pointer. Depending on your use, you might want to check the reflect value kind before calling Elem().
I have a function that is being generated using reflection and reflect.MakeFunc, so I don't actually have the return type until runtime.
Inside the template function that MakeFunc is using, is there a way to determine the return type of the concrete function being templated?
Essentially, is there a way to determine the return type iof the currently executing function at runtime?
I know about the Out method:
fn.Type().Out(0)
And I can find the return type of a function easily enough?
But is there a way to find the return type of the currently executing function (as opposed to an explicit passed function reference).
You should check fn.Type().Out(0).Kind(), for example:
func main() {
fnTmpl := func(in []reflect.Value) []reflect.Value {
return []reflect.Value{in[0]}
}
makeFn := func(fptr interface{}) {
fn := reflect.ValueOf(fptr).Elem()
fn.Set(reflect.MakeFunc(fn.Type(), fnTmpl))
}
var nFn func(int) int
makeFn(&nFn)
kind := reflect.TypeOf(nFn).Out(0).Kind()
switch kind {
case reflect.Int:
fmt.Println("int")
}
}
In the case you are talking about, the return type of the currently executing function is always []reflect.Type (because that is what a function passed to reflect.MakeFunc must return). What you really want is the return type of the reflect.makeFuncStub function that called your function.
There is no way to get that (except perhaps some strange inspection of the call stack), but you can make an enhanced version of MakeFunc that provides the information:
package main
import (
"fmt"
"reflect"
)
// MakeFunc is like reflect.MakeFunc, but fn has an extra argument, retType, which
// is passed the desired return type.
func MakeFunc(typ reflect.Type, fn func(args []reflect.Value, retType reflect.Type) (results []reflect.Value)) reflect.Value {
if n := typ.NumOut(); n != 1 {
panic("wrong number of return values")
}
rt := typ.Out(0)
return reflect.MakeFunc(typ, func(args []reflect.Value) (results []reflect.Value) {
return fn(args, rt)
})
}
func makeReturnOne(fptr interface{}) {
fn := reflect.ValueOf(fptr).Elem()
fn.Set(MakeFunc(fn.Type(), returnOne))
}
func returnOne(args []reflect.Value, retType reflect.Type) []reflect.Value {
ret := reflect.New(retType).Elem()
switch retType.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
ret.SetInt(1)
case reflect.Float32, reflect.Float64:
ret.SetFloat(1.0)
default:
panic("returnOne only supports int and float types")
}
r := ret.Interface()
fmt.Printf("returning %v as %T\n", r, r)
return []reflect.Value{ret}
}
func main() {
var r1f func() float64
var r1i func() int
makeReturnOne(&r1f)
makeReturnOne(&r1i)
fmt.Println(r1f())
fmt.Println(r1i())
}
I might have misinterpreted what you are trying to achieve, but why not just take the kind of the value you are returning? Modifying OneOfOne's example as follows:
fnTmpl := func(in []reflect.Value) (res []reflect.Value) {
res = []reflect.Value{in[0]}
fmt.Println("Returned:", res[0].Kind())
return res
}
Playground: http://play.golang.org/p/EujmxyGRrI