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
Related
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)
}
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
}
How do you create a slice of functions with different signatures? I tried the code below but its feels hack-ish. Do we just bite the bullet and use a slice interface{}?
package main
import (
"fmt"
)
type OneParams func(string) string
type TwoParams func(string, string) string
type ThreeParams func(string, string, string) string
func (o OneParams) Union() string {
return "Single string"
}
func (t TwoParams) Union() string {
return "Double string"
}
func (t ThreeParams) Union() string {
return "Triple string"
}
type Functions interface {
Union() string
}
func Single(str string) string {
return str
}
func Double(str1 string, str2 string) string {
return str1 + " " + str2
}
func Triple(str1 string, str2 string, str3 string) string {
return str1 + " " + str2 + " " + str3
}
func main() {
fmt.Println("Slice Of Functions Program!\n\n")
fSlice := []Functions{
OneParams(Single),
TwoParams(Double),
ThreeParams(Triple),
}
for _, value := range fSlice {
switch t := value.(type) {
case OneParams:
fmt.Printf("One: %s\n", t("one"))
case TwoParams:
fmt.Printf("Two: %s\n", t("one", "two"))
case ThreeParams:
fmt.Printf("Three: %s\n", t("one", "two", "three"))
default:
fmt.Println("Huh! What's that?")
}
}
fmt.Println("\n\n")
}
Is this just a case of trying to do too much with Go?
Please check it, I don't know if it what you want. Because I don't know what are you exactly want.
package main
import (
"fmt"
"reflect"
)
func A() {
fmt.Println("A")
}
func B(A int) {
fmt.Println("B", A)
}
func C(A string, B float32) {
fmt.Println("C", A, B)
}
func main() {
f := []interface{}{A, B, C}
f[0].(func())()
f[1].(func(int))(15)
f[2].(func(string, float32))("TEST", 90)
fmt.Println("\n******* another thing ******")
for a, v := range f {
v := reflect.TypeOf(v)
fmt.Println("#######", a)
fmt.Println("num param :", v.NumIn())
for i := 0; i < v.NumIn(); i++ {
fmt.Println("param :", i, "type is ", v.In(i))
}
}
}
Check on Go Playground
Here I have another example calling using reflect
package main
import (
"fmt"
"reflect"
)
func A() {
fmt.Println("A")
}
func B(A int) {
fmt.Println("B", A)
}
func C(A string, B float32) {
fmt.Println("C", A, B)
}
func main() {
f := []interface{}{A, B, C}
f[0].(func())()
f[1].(func(int))(15)
f[2].(func(string, float32))("TEST", 90)
fmt.Println("\n******* calling with reflect ******")
for a, v := range f {
v := reflect.TypeOf(v)
//calling the function from reflect
val := reflect.ValueOf(f[a])
params := make([]reflect.Value, v.NumIn())
if v.NumIn() == 1 {
params[0] = reflect.ValueOf(1564)
} else if v.NumIn() == 2 {
params[0] = reflect.ValueOf("Test FROM reflect")
params[1] = reflect.ValueOf(float32(123456))
}
val.Call(params)
}
}
Check on Go Playground
depends on what the different you need. upon your example, we could use variadic.
package main
import(
"fmt"
"strings"
)
func foo(ss ...string) string{
return strings.Join(ss, " ")
}
func main(){
fmt.Println(foo("one"))
fmt.Println(foo("one", "two"))
fmt.Println(foo("one", "two", "three"))
}
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()
}
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...)
}