Return values of function as input arguments to another
Asked Answered
C

3

17

If I have

func returnIntAndString() (i int, s string) {...}

And I have:

func doSomething(i int, s string) {...}

Then I can do the following successfully:

doSomething(returnIntAndString())

However, let's say I want to add another argument to doSomething like:

func doSomething(msg string, i int, s string) {...}

Go complains when compiling if I call it like:

doSomething("message", returnIntAndString())

With:

main.go:45: multiple-value returnIntAndString() in single-value context
main.go:45: not enough arguments in call to doSomething()

Is there a way to do this or should I just give up and assign the return values from returnIntAndString to some references and pass msg and these values like doSomething(msg, code, str) ?

Ciao answered 8/2, 2016 at 16:31 Comment(1)
It'd be helpful if you posted the rest of the codePeccable
C
18

It's described here in the spec. It requires the inner function to return the correct types for all arguments. There is no allowance for extra parameters along with a function that returns multiple values.

As a special case, if the return values of a function or method g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order. The call of f must contain no parameters other than the call of g, and g must have at least one return value. If f has a final ... parameter, it is assigned the return values of g that remain after assignment of regular parameters.

func Split(s string, pos int) (string, string) {
  return s[0:pos], s[pos:]
}

func Join(s, t string) string {
  return s + t
}

if Join(Split(value, len(value)/2)) != value {
  log.Panic("test fails")
}

If those specific conditions are not met, then you need to assign the return values and call the function separately.

Carnatic answered 8/2, 2016 at 16:36 Comment(0)
S
1

I had the same question. The best solution I could come up with is creating types or structs for my desired extra parameters and writing methods for them like this:

package main

import (
    "fmt"
)

type Message string

type MessageNumber struct {
    Message string
    Number int
}

func testfunc() (foo int, bar int) {
    foo = 4
    bar = 2
    return
}

func (baz Message) testfunc2(foo int, bar int) {
    fmt.Println(foo, bar, baz)
}

func (baz MessageNumber) testfunc3(foo int, bar int) {
    fmt.Println(foo, bar, baz.Number, baz.Message)
}

func main() {
    Message("the answer").testfunc2(testfunc())
    MessageNumber{"what were we talking about again?", 0}.testfunc3(testfunc())
    fmt.Println("Done.  Have a day.")
}

The output looks like this:

user@Frodos-Atari-MEGA-STE:~/go/test$ go run main.go
4 2 the answer
4 2 0 what were we talking about again?
Done.  Have a day.
Sixtasixteen answered 27/3, 2021 at 23:22 Comment(0)
T
0

My solution is to create function, that returns a function that takes the extra parameters.

In this example the extra parameter is a function.

func ValueAndErr(...) (V, error) {
    // ...
    return V, err // err may be nil
}

// What I wanted to do at first
func GetValueAndDoSomethingIfErr[T any](v T, err error, callback func(error)) T {
    if err != nil {
        callback(err)
    }
    return v
}

// This does not compile :c
// But I would have to assign output of the function ValueAndErr() to variables
GetValueAndDoSomethingIfErr(
    ValueAndErr(...),
    func(err error) { ... },
)


func GetValueAndDoSomethingIfErr[T any](v T, err error) func(callback func(error)) T {
    return func(callback func(err error)) T {
        if err != nil {
            callback(err)
        }
        return v
    }
}

// This works :DD
GetValueAndDoSomethingIfErr(ValueAndErr(...))(func(err error) { ... })

I don't know if this solution is efficient, or a good practice. It works though, and I kinda like it. Any feedback is appreciated :D

Thankless answered 30/12, 2023 at 22:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.