I've been struggling with golang's lack of optional parameters, so I have been using the closest workaround: variadics. Even though I got it working, it is messy attempting to pass multiple variable types to the same variadic parameter by reference:
// back-end
func UpdateRef(variadic ...*interface{}) {
for _, v := range variadic {
if v.(type) == string {
*v = "New ref val"
}
}
}
// front-end
func Interface(x interface{}) interface{} { return &x }
func main() {
ref := Interface("Hey") // starts as "Hey"
i := Interface(500)
UpdateRef(&ref, &i) // ends at "New ref val"
}
If I replace the front-end with this:
// front-end
func main() {
ref := "Hey" // starts as "Hey"
UpdateRef(ref, 500) // ends at "New ref val"
}
...then how could I change the back-end to make the desired front-end code work? The back-end can be as verbose as need be, so long as the desired front-end runs as is. Is this possible? If not, is there an elegant solution that requires minimal changes to the desired front-end?
CodePudding user response:
Use interface{}
as the argument type. Type assert to pointer types.
Dereference pointers to set the values.
func UpdateRef(variadic ...interface{}) {
for _, v := range variadic {
if v, ok := v.(*string); ok {
*v = "New ref val"
}
}
}
Pass pointers to the function:
ref := "Hey"
i := 500
UpdateRef(&ref, &i)
fmt.Println(ref) // prints “New ref val”
CodePudding user response:
you just
package main
import (
"reflect"
)
// back-end
func UpdateRef(variadic ...interface{}) {
for _, v := range variadic {
kind := reflect.TypeOf(v).Kind()
if kind == reflect.Pointer {
reflect.ValueOf(v).Elem().Set(reflect.ValueOf("New ref val"))
}
}
}
// front-end
func main() {
ref := "Hey" // starts as "Hey"
// To modify a reflection object, the value must be settable.
UpdateRef(&ref, 500) // ends at "New ref val"
println(ref)
}
check out the golang blog:https://go.dev/blog/laws-of-reflection.
Coding Happy!