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) ?

1
  • It'd be helpful if you posted the rest of the code Commented Feb 8, 2016 at 16:35

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.