传递两个返回值以使用一个参数起作用

时间:2018-06-18 18:18:00

标签: go

我想这样做:

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

问题是,strconv.Atoi需要一个参数,但reader.ReadString()不仅返回字符串,还返回" err"。有没有办法解决这个问题而不创建变量或一般只在一行?

2 个答案:

答案 0 :(得分:0)

在Go中执行此操作的惯用方法是使用通常的if err != nil优雅地处理错误。使用它。

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

如果您想使代码“更干净”,请将其拆分为函数。

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

为了完整起见,在某些情况下忽略错误是有用的,因为你知道不会有任何错误。这种情况包括始终给出相同输入的解析器,即。正则表达式和模板。这些提供了有用的习语“必须”:例如,regexp.MustCompile是一个非常简单的regexp.Compile包装器,如果它不是零,它会检查错误和恐慌。

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

当有一个正则表达式用作单例并在全局范围内声明时,这在Go程序中最常见。

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

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

Playground

为了帮助考虑何时使用或添加“必须”功能,我将其视为“如果Go中有一种方法可以添加编译时检查,那么这将是一个好用的地方它”。

正如我所说,Go标准库的模板包中也提供了这一点,例如html/template。这些并不能为所有内容提供必需功能,但它们具有简单的template.Must功能(更接近于您在OP中尝试的功能)。通过这种方式,您可以“链接”通常会返回模板和错误的函数,以便它们只返回模板(如果有任何错误,则会发生混乱)。

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

这很有效,因为template.Must有一个签名func(*Template, error),而Parse返回(*Template, error),所以返回值和函数参数匹配。例如,如果strconv.Atoi具有签名func(string, error),那么您的示例可能有用。

答案 1 :(得分:0)

在Go中,编写一个readInt函数以隐藏复杂性并始终检查错误。其他答案也有错误:Howl(删除最后一个数字)和Raduan Santos(未编译)。

例如,

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

输出:

93 31 11 11
93
31
11
11