Here's a small example using an array of functions. I want to convert this to an array of receiver methods. What would be the proper declaration for the array on line 11? https://play.golang.org/p/G62Cxm-OG2
The function declarations would change from:
func addToStock(s *Stock, add int)
To:
func (s *Stock) addToStock(add int)
You can do like these:
package main
import (
"fmt"
)
type Stock struct {
qty int
}
var updaters = [2]func(*Stock, int){
func(s *Stock, i int){s.add(i)},
func(s *Stock, i int){s.remove(i)},
}
func main() {
s := Stock{10}
fmt.Println("Stock count =", s.qty)
updaters[0](&s, 2)
fmt.Println("Stock count =", s.qty)
updaters[1](&s, 5)
fmt.Println("Stock count =", s.qty)
}
func (s *Stock)add(add int) {
s.qty += add
}
func (s *Stock)remove(sub int) {
s.qty -= sub
}
Related
func (s *TODOService) DeleteTODO(ctx context.Context, ids []int64) error {
const deleteFmt = `DELETE FROM todos WHERE id IN (?%s)`
return nil
}
I need to add as many Symbols (here ?) to the Query as the number of id lists, so I want to combine the fmt.Sprintf and strings.Repeat functions to add Symbols to the provided Query Format How should I add it?
ipml Stringer interface
package main
import (
"fmt"
"strconv"
"strings"
)
type SqlArr []int64
func (a SqlArr) String() string {
ans := strings.Builder{}
for i := 0; i < len(a); i++ {
ans.WriteString(strconv.FormatInt(a[i], 10))
if i != len(a)-1 {
ans.WriteRune(',')
}
}
return ans.String()
}
func Test(ids SqlArr) {
deleteFmt := fmt.Sprintf(`DELETE FROM todos WHERE id IN (%s)`, ids)
fmt.Printf("%v\n", deleteFmt)
}
func main() {
Test([]int64{1, 2, 3})
}
I'm experimenting with using Go's reflection library and have come to an issue I cannot figure out: How does one call on a function returned from calling a closure function via reflection? Is it possible to basically have a sequence of:
func (f someType) closureFn(i int) int {
return func (x int) int {
return x+i
}
}
...
fn := reflect.ValueOf(&f).MethodByName("closureFn")
val := append([]reflect.Value{}, reflect.ValueOf(99))
fn0 := fn.Call(val)[0]
fn0p := (*func(int) int)(unsafe.Pointer(&f0))
m := (*fn0p)(100)
Which should get m to equal 199?
The following is the simplified code that demonstrates the issue. The call to the "dummy" anonymous function works ok, as does the reflective call to the closure. However attempts at calling on the closure return fail with a nil pointer (the flag set on the address of the Value in the debugger is 147, which comes down to addressable).
Any suggestions on what's going on, or if it's at all possible are welcome.
Link to playground: https://play.golang.org/p/0EPSCXKYOp0
package main
import (
"fmt"
"reflect"
"unsafe"
)
// Typed Struct to hold the initialized jobs and group Filter function types
type GenericCollection struct {
jobs []*Generic
}
type Generic func (target int) int
func main() {
jjf := &GenericCollection{jobs: []*Generic{}}
jjf.JobFactoryCl("Type", 20)
}
// Returns job function with closure on jobtype
func (f GenericCollection) Job_by_Type_Cl(jobtype int) (func(int) int) {
fmt.Println("Job type is initialized to:", jobtype)
// Function to return
fc := func(target int) int {
fmt.Println("inside JobType function")
return target*jobtype
}
return fc
}
// Function factory
func (f GenericCollection) JobFactoryCl(name string, jobtype int) (jf func(int) int) {
fn := reflect.ValueOf(&f).MethodByName("Job_by_" + name + "_Cl")
val := append([]reflect.Value{}, reflect.ValueOf(jobtype))
if fn != reflect.ValueOf(nil) {
// Reflected function -- CALLING IT FAILS
f0 := fn.Call(val)[0]
f0p := unsafe.Pointer(&f0)
//Local dummy anonymous function - CALLING IS OK
f1 := func(i int) int {
fmt.Println("Dummy got", i)
return i+3
}
f1p := unsafe.Pointer(&f1)
// Named function
pointers := []unsafe.Pointer{f0p, f1p}
// Try running f1 - OK
f1r := (*func(int) int)(pointers[1])
fmt.Println((*f1r)(1))
(*f1r)(1)
// Try calling f0 - FAILS. nil pointer dereference
f0r := (*func(int) int)(pointers[0])
fmt.Println((*f0r)(1))
jf = *f0r
}
return jf
}
Type assert the method value to a function with the appropriate signature. Call that function.
First example from the question:
type F struct{}
func (f F) ClosureFn(i int) func(int) int {
return func(x int) int {
return x + i
}
}
func main() {
var f F
fn := reflect.ValueOf(&f).MethodByName("ClosureFn")
fn0 := fn.Call([]reflect.Value{reflect.ValueOf(99)})[0].Interface().(func(int) int)
fmt.Println(fn0(100))
// It's also possible to type assert directly
// the function type that returns the closure.
fn1 := fn.Interface().(func(int) func(int) int)
fmt.Println(fn1(99)(100))
}
Run it on the Playground
Second example from the question:
func (f GenericCollection) JobFactoryCl(name string, jobtype int) func(int) int {
jf := reflect.ValueOf(&f).MethodByName("Job_by_" + name + "_Cl").Interface().(func(int) func(int) int)
return jf(jobtype)
}
func main() {
jjf := &GenericCollection{jobs: []*Generic{}}
jf := jjf.JobFactoryCl("Type", 20)
fmt.Println(jf(10))
}
Run it on the Playground
Is there anyway to make a map of function pointers, but functions that take recievers? I know how to do it with regular functions:
package main
func someFunc(x int) int {
return x
}
func main() {
m := make(map[string]func(int)int, 0)
m["1"] = someFunc
print(m["1"](56))
}
But can you do that with functions that take recievers? Something like this (though I've tried this and it doesn't work):
package main
type someStruct struct {
x int
}
func (s someStruct) someFunc() int {
return s.x
}
func main() {
m := make(map[string](someStruct)func()int, 0)
s := someStruct{56}
m["1"] = someFunc
print(s.m["1"]())
}
An obvious work around is to just pass the struct as a parameter, but that's a little dirtier than I would have liked
You can do that using Method Expressions:
https://golang.org/ref/spec#Method_expressions
The call is a bit different, since the method expression takes the receiver as the first argument.
Here's your example modified:
package main
type someStruct struct {
x int
}
func (s someStruct) someFunc() int {
return s.x
}
func main() {
m := make(map[string]func(someStruct)int, 0)
s := someStruct{56}
m["1"] = (someStruct).someFunc
print(m["1"](s))
}
And here's a Go playground for you to test it:
https://play.golang.org/p/PLi5A9of-U
Assume there is a function that returns two variables.
func num(a,b int) (int,int) {
return a+b, a-b
}
http://play.golang.org/p/bx05BugelV
And assume I have a function that only takes one int value.
package main
import "fmt"
func main() {
fmt.Println("Hello, playground")
_, a := num(1, 2)
prn(a)
}
func num(a, b int) (int, int) {
return a + b, a - b
}
func prn(a int) {
fmt.Println(a)
}
http://play.golang.org/p/VhxF_lbVf4
Is there anyway I can only get the 2nd value (a-b) without having _,a:=num(1,2)??
Something like prn(num(1,2)[1]) <-- this won't work, but I'm wondering if there's a similar way
Thank you
Use a wrapper function. For example,
package main
import "fmt"
func main() {
_, a := num(1, 2)
prn(a)
prn1(num(1, 2))
}
func num(a, b int) (int, int) {
return a + b, a - b
}
func prn(a int) {
fmt.Println(a)
}
func prn1(_, b int) {
prn(b)
}
Output:
-1
-1
I try to write a function which takes any other function and wraps a new function around it. This is what I have tried so far:
package main
import (
"fmt"
)
func protect (unprotected func (...interface{})) (func (...interface{})) {
return func (args ...interface{}) {
fmt.Println ("protected");
unprotected (args...);
};
}
func main () {
a := func () {
fmt.Println ("unprotected");
};
b := protect (a);
b ();
}
When I compile this I get the error:
cannot use a (type func()) as type func(...interface { }) in function argument
Why is a function without arguments not compatible to a function with a variable number of arguments? What can I do to make them compatible?
Update:
The protected function should be compatible with the original:
func take_func_int_int (f func (x int) (y int)) (int) {
return f (1)
}
func main () {
a := func (x int) (y int) {
return 2 * x
}
b := protect (a)
take_func_int_int (a)
take_func_int_int (b)
}
Types are pretty concrete in Go. You could try
a := func(_ ...interface{}) {
fmt.Println("unprotected")
}
func (...interface{}) does not mean "any function that takes any number of any kind of arguments", it means "only a function which takes a variable number of interface{} arguments"
Alternatively rather than func(...interface{}) you can just use interface{} and the reflect package. See http://github.com/hoisie/web.go for an example.
EDIT: Specifically, this:
package main
import (
"fmt"
"reflect"
)
func protect(oldfunc interface{}) (func (...interface{})) {
if reflect.TypeOf(oldfunc).Kind() != reflect.Func {
panic("protected item is not a function")
}
return func (args ...interface{}) {
fmt.Println("Protected")
vargs := make([]reflect.Value, len(args))
for n, v := range args {
vargs[n] = reflect.ValueOf(v)
}
reflect.ValueOf(oldfunc).Call(vargs)
}
}
func main() {
a := func() {
fmt.Println("unprotected")
}
b := func(s string) {
fmt.Println(s)
}
c := protect(a)
d := protect(b)
c()
d("hello")
}
Ouput is
Protected
unprotected
Protected
hello
EDIT: To answer the update
Like I said above, types are pretty concrete in Go. The protect function returns a type func(...interface{}) which will never be assignable to func(int)int. I think you're probably either over-engineering your problem or misunderstanding it. However, here's a highly discouraged code snippet that would make it work.
First change protect to also return values:
func protect(oldfunc interface{}) (func (...interface{}) []interface{}) {
if reflect.TypeOf(oldfunc).Kind() != reflect.Func {
panic("protected item is not a function")
}
return func (args ...interface{}) []interface{} {
fmt.Println("Protected")
vargs := make([]reflect.Value, len(args))
for n, v := range args {
vargs[n] = reflect.ValueOf(v)
}
ret_vals := reflect.ValueOf(oldfunc).Call(vargs)
to_return := make([]interface{}, len(ret_vals))
for n, v := range ret_vals {
to_return[n] = v.Interface()
}
return to_return
}
}
Then make a convert function:
func convert(f func(...interface{}) (func(int) int) {
return func(x int) int {
r := f(x)
return r[0].(int)
}
}
Then your call would look like
take_func_int_int(convert(b))
But I promise this isn't what you actually want to do.
Step back and try to rework the problem. I've completely killed type-safety in these examples. What are you trying to accomplish?
package main
import "fmt"
// Here's a function that will take an arbitrary number
// of `int`s as arguments.
func sum(nums ...int) {
fmt.Print(nums, " ")
total := 0
for _, num := range nums {
total += num
}
fmt.Println(total)
}
func main() {
// Variadic functions can be called in the usual way
// with individual arguments.
sum(1, 2)
sum(1, 2, 3)
// If you already have multiple args in a slice,
// apply them to a variadic function using
// `func(slice...)` like this.
nums := []int{1, 2, 3, 4}
sum(nums...)
}