将两个返回值传递给具有一个参数的函数

I want to do this:

R, _ := strconv.Atoi(reader.ReadString(" ")) // reader = bufio.NewReader()

and the problem is, that strconv.Atoi expects one argument, but reader.ReadString() returns not only the string, but also the "err". Is there a way to solve this without creating variables or generally on just one line?

In Go, write a readInt function to hide the complexity and always check for errors. Other answers have bugs: Howl (drops last number) and Raduan Santos (doesn't compile).

For example,

package main

import (
    "bufio"
    "fmt"
    "io"
    "log"
    "strconv"
    "strings"
)

func readInt(r *bufio.Reader) (int, error) {
    const delim = ' '
    str, err := r.ReadString(delim)
    if err != nil && len(str) == 0 {
        return 0, err
    }
    str = strings.TrimSuffix(str, string(delim))
    return strconv.Atoi(str)
}

func main() {
    input := "93 31 11 11"
    fmt.Println(input)
    rdr := bufio.NewReader(strings.NewReader(input))
    for {
        n, err := readInt(rdr)
        if err != nil {
            if err == io.EOF {
                break
            }
            log.Fatal(err)
        }
        fmt.Println(n)
    }
}

Output:

93 31 11 11
93
31
11
11

The idiomatic way to do it in Go is to handle the error gracefully with the usual if err != nil. Use it.

reader := bufio.NewReader(strings.NewReader("93 31 11 11"))
numRaw, err := reader.ReadString(' ')
if err != nil {
    log.Fatal(err)
}
// We need to substring numRaw because it contains also the trailing space (this is how ReadString works in bufio.Reader)
num, err := strconv.Atoi(numRaw[:len(numRaw)-1])
if err != nil {
    log.Fatal(err)
}
log.Print(num)

Playground

If you want to make the code "cleaner", split it into functions.

func main() {
    reader := bufio.NewReader(strings.NewReader("93 31 11 11"))
    n, err := readInt(reader)
    if err != nil {
        log.Fatal(err)
    }
    log.Print(n)
}

func readInt(r *bufio.Reader) (int, error) {
    numRaw, err := r.ReadString(' ')
    if err != nil {
        return 0, err
    }
    return strconv.Atoi(numRaw[:len(numRaw)-1])
}

Playground


For sake of completeness, there are some cases where it is useful to ignore the error because you know there won't be any. Such cases include parser which are always given the same input, ie. regexes and templates. These provide the useful idiom "Must": for instance, regexp.MustCompile is a very simple wrapper around regexp.Compile, which checks the error and panics if it's not nil.

func MustCompile(str string) *Regexp {
    regexp, error := Compile(str)
    if error != nil {
        panic(`regexp: Compile(` + quote(str) + `): ` + error.Error())
    }
    return regexp
}

This is most often seen in Go programs when there is a regex which is used as a singleton and is declared in the global scope.

var usernameRegex = regexp.MustCompile("^[0-9A-Za-z-]+$")

func main() {
    fmt.Println(usernameRegex.MatchString("Hello"))
    fmt.Println(usernameRegex.MatchString(""))
}

Playground

To help think about when it is useful to use or add a "Must" function, I think of it as "If there was a way in Go to add a compile-time check, this would be a good place to use it".

As I said, this is also provided in the template packages of the Go standard library, such as html/template. These don't provide a Must- function for everything, but they have a simple template.Must function (which is closer to what you were trying to do in the OP). This way you can "chain" functions which would normally return a template and an error, so that they only return the template (and panic if there is any error).

var t = template.Must(template.New("hi").Parse(`{{ if .Bool }}Hello{{ else }}Goodbye{{ end }} world!`))

func main() {
    t.ExecuteTemplate(os.Stdout, "hi", struct{Bool bool}{Bool: false})
}

Playground

This works, because template.Must has a signature func(*Template, error), and Parse returns (*Template, error), so return values and function arguments match. For instance, your example could have worked if strconv.Atoi had the signature func(string, error).