Passing for loop values as function parameters - go

It says: (no value) used as value, but I'm passing loop values from a slice to it!
package main
import "fmt"
func greet(n string) {
fmt.Printf("Hi, %v\n", n)
}
func cycle(n []string, f func(string)) {
for i := 0; i < len(n); i++ {
fmt.Println(f(n[i]))
}
}
func main() {
cycle([]string{"John", "Marie"}, greet)
}
Code snippet on Go Playground

I found the solution: I should have called the function directly, not inside Println().
package main
import "fmt"
func greet(n string) {
fmt.Printf("Hi, %v\n", n)
}
func cycle(n []string, f func(string)) {
for i := 0; i < len(n); i++ {
f(n[i])
}
}
func main() {
cycle([]string{"John", "Marie"}, greet)
}

Related

Check if a method type matches a function type

Given the following example, how to check if a method matches a function signature?
package main
import (
"fmt"
"context"
"reflect"
)
// signature to check
type Fn func(context.Context)
type testStruct struct {}
func (*testStruct) DoSomething(context.Context){}
func (*testStruct) DoSomethingElse([]byte){}
func main() {
structType := reflect.TypeOf(&testStruct{})
for i := 0; i < structType.NumMethod(); i++ {
fmt.Println("======================")
method := structType.Method(i)
fmt.Println(method.Name)
fmt.Println(method.Type.String())
// compare method and Fn signature
}
}
https://play.golang.org/p/rIDfp0E14ge
1. Using reflect.Value.Type().ConvertibleTo
Note the reflect.ValueOf insted of reflect.TypeOf
package main
import (
"context"
"fmt"
"reflect"
)
type Fn func(context.Context)
type testStruct struct{}
func (*testStruct) DoSomething(context.Context) {}
func (*testStruct) DoSomethingElse([]byte) {}
func (*testStruct) DoSomethingElse2(context.Context) error { return nil }
func main() {
structType := reflect.ValueOf(&testStruct{})
for i := 0; i < structType.NumMethod(); i++ {
fmt.Println("======================")
method := structType.Method(i)
// compare method and Fn
if method.Type().ConvertibleTo(reflect.TypeOf((Fn)(nil))) {
fmt.Println("function of correct type")
}
}
}
https://play.golang.org/p/A9_bpURinad
2. Checking inputs and outputs individually
package main
import (
"context"
"fmt"
"reflect"
)
type Fn func(context.Context)
type testStruct struct{}
func (*testStruct) DoSomething(context.Context) {}
func (*testStruct) DoSomethingElse([]byte) {}
func main() {
structType := reflect.TypeOf(&testStruct{})
rctx := reflect.TypeOf(new(context.Context)).Elem()
for i := 0; i < structType.NumMethod(); i++ {
fmt.Println("======================")
method := structType.Method(i)
fmt.Println(method.Name)
fmt.Println(method.Type.String())
if method.Type.NumIn() != 2 {
fmt.Println("wrong number of inputs, expected 1")
continue
}
if method.Type.In(1) != rctx {
fmt.Println("input of wrong type, expected context.Context")
continue
}
if method.Type.NumOut() != 0 {
fmt.Println("wrong number of outputs, expected 0")
continue
}
fmt.Printf("%v is a function of correct type\n", method.Name)
}
}
https://play.golang.org/p/YDsJ9MSiumF

Why I am getting non-numeric type *int error?

I am getting non-numeric type *int error in the example below, why ?
func main() {
count := 0
for {
counting(&count)
}
}
func counting(count *int) {
fmt.Println(count)
count++
}
You need to derefence the pointer:
package main
import (
"fmt"
)
func main() {
count := 0
for i:=0; i<10; i++ {
counting(&count)
}
}
func counting(count *int) {
fmt.Println(*count)
*count++
}

Golang multiple-value function composition

Short question to which I haven't found an answer on SO: how do I write composite function calls when an inner function has multiple return values?
Sub-question: can you cast just one of the returns from a multiple-value function without using a temp variable?
Example: http://play.golang.org/p/intnxkzSO1
package main
import "fmt"
func multiReturn() (int, int) {
return 0, 1
}
func noOp(a int) int {
return a
}
func main() {
// Too many arguments
fmt.Print(noOp(multiReturn()))
// multiple-value in single-value context
fmt.Print(string(multiReturn()))
}
You can have your outer function match the return values of the inner function
func multiReturn() (int, int) {
return 10, 1
}
func noOp(a, _ int) int {
return a
}
func main() {
fmt.Printf("%v\n", noOp(multiReturn())) // output: 10
fmt.Printf("%s", strconv.Itoa(noOp(multiReturn()))) // output: 10
}
On a side note string(int) will not work, you have to use the strconv package.
Go play
Another option would to use a variadic parameter.
func noOp(a ...int) int {
if len(a) > 0 {
return a[0]
}
return 0
}
For example,
package main
import "fmt"
func singleReturn() int {
s, _ := multiReturn()
return s
}
func multiReturn() (int, int) {
return 0, 1
}
func noOp(a int) int {
return a
}
func main() {
fmt.Print(noOp(singleReturn()))
fmt.Print(string(singleReturn()))
// Too many arguments
//fmt.Print(noOp(multiReturn()))
// multiple-value in single-value context
//fmt.Print(string(multiReturn()))
}
you can also return a function that returns multiple values.
func f() (int, int) {
return 1, 2
}
func g() (int, int) {
return f()
}

GO: find/scan for structs/functions

Is it possible in GO to find structs or functions by criteria such as name, tag or interface? i.e something along the lines of command line tasks/verbs? i.e:
func cmd1() {
...
}
func cmd2() {
...
}
...
func cmdN() {
}
func main() {
// Inspect os.Args and call cmd{X}() based on args.
...
}
I don't mind what the exact mechanism is and if the final targets are functions or structs - the goal is to get something working by convention without any boilerplate code.
You could use reflection
package main
import (
"flag"
"fmt"
"reflect"
)
var cmd command
type command struct{}
func (c command) execute(name string) {
v := reflect.ValueOf(c)
cmd := v.MethodByName(name)
if !cmd.IsValid() {
fmt.Println(name + " not a command")
return
}
cmd.Call([]reflect.Value{})
}
func (c command) Cmd1() {
fmt.Println("command 1")
}
func (c command) Cmd2() {
fmt.Println("command 2")
}
func (c command) Cmd3() {
fmt.Println("command 3")
}
func main() {
flag.Parse()
cmd.execute(flag.Arg(0))
}
or you could use a map.
package main
import (
"flag"
"fmt"
)
func cmd1() {
fmt.Println("command 1")
}
func cmd2() {
fmt.Println("command 2")
}
func cmd3() {
fmt.Println("command 3")
}
var funcs = map[string]func(){
"cmd1": cmd1,
"cmd2": cmd2,
"cmd3": cmd3,
}
func main() {
flag.Parse()
if f, ok := funcs[flag.Arg(0)]; ok {
f()
} else {
fmt.Println(flag.Arg(0) + " command not found")
}
}
I used a similar approach in "How to test a collection of functions by reflection in Go?"
The idea is to list and find all the functions needed, in my case, functions for a certain struct type:
stype := reflect.ValueOf(s)
for _, fname := range funcNames {
sfunc := stype.MethodByName(fname)
// no parameter => empty slice of Value
ret := sfunc.Call([]reflect.Value{})

GoLang: Allocating Slice of Slices in functions results in index out of range

I've been trying some things out in Go and I've hit a problem that I can't figure out.
package main
import "fmt"
import "strconv"
func writeHello(i int, ) {
fmt.Printf("hello, world "+strconv.Itoa(i)+"\n")
}
type SliceStruct struct {
data [][]int;
}
func (s SliceStruct) New() {
s.data=make([][]int,10);
}
func (s SliceStruct) AllocateSlice(i int) {
s.data[i]=make([]int,10);
}
func (s SliceStruct) setData(i int, j int, data int) {
s.data[i][j] = data;
}
func (s SliceStruct) getData(i int, j int) int {
return s.data[i][j]
}
func useSliceStruct(){
sliceStruct := SliceStruct{};
sliceStruct.New();
for i := 0; i < 10; i++ {
sliceStruct.AllocateSlice(i);
for j:=0; j<10; j++ {
sliceStruct.setData(i,j,i);
writeHello(sliceStruct.getData(i,j));
}
}
}
func dontUseSliceStruct(){
data:=make([][]int,10);
for i := 0; i < 10; i++ {
data[i]=make([]int,10);
for j:=0; j<10; j++ {
data[i][j] = i;
writeHello(data[i][j]);
}
}
}
func main() {
dontUseSliceStruct();
useSliceStruct();
}
When it gets to the function useSliceStruct, the code fails at the first call to AllocateSlice() with an index out of range error.
As far as I can tell the code for the two methods does idential things. So what am I missing?
DOH, just worked it out.
I wasn't using a reference to the struct in the function declarations.
func (s SliceStruct)
Should have been
func (s *SliceStruct)

Resources