实现 io.Reader 时无限循环中中断与返回的不同行为

我正在经历正式的旅行。

问题是当我使用break而不是 时return ttl, io.EOF,程序会进入无限循环。但是,据我所知,在这个程序中,与breakor应该没有区别return ttl, io.EOF,因为如果是break,下一行将return ttl, err在方法的末尾Read(),这与 相同return ttl, io.EOF

我想知道为什么。与 Go 如何处理 io.Reader 接口及其实现的底层机制有关吗?

这是代码。

package main


import (

    "io"

    "os"

    "strings"

)


type rot13Reader struct {

    r io.Reader

}


func (rr *rot13Reader) Read(b []byte) (n int, err error) {

    rb := make([]byte, 8)

    var ttl int

    for {

        n, err := rr.r.Read(rb)

        if err == io.EOF {

            return ttl, io.EOF

            // break <----------------------------here's the problem

        } else if err != nil {

            panic(err)

        } else {

            for i, c := range rb[:n] {

                b[i+ttl] = decodeRot13(c)

            }

            ttl += n

        }

    }

    return ttl, err

}


func decodeRot13(c byte) byte {

    if c >= 97 && c <= 122 { // a-z: 97 122

        c += 13

        if c > 122 {

            c -= 26

        }

    } else if c >= 65 && c <= 90 { // A-Z: 65 90

        c += 13

        if c > 90 {

            c -= 26

        }

    }

    return c

}


func main() {

    s := strings.NewReader("Lbh penpxrq gur pbqr!")

    r := rot13Reader{s}

    io.Copy(os.Stdout, &r)

}


肥皂起泡泡
浏览 78回答 1
1回答

弑天下

观察到的行为是由于变量阴影造成的:func (rr *rot13Reader) Read(b []byte) (n int, err error) { // <-- this 'err'&nbsp; &nbsp; rb := make([]byte, 8)&nbsp; &nbsp; var ttl int&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; n, err := rr.r.Read(rb) // <-- and this 'err' are different&nbsp; &nbsp; &nbsp; &nbsp; if err == io.EOF {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return ttl, io.EOF&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // break <----------------------------here's the problem&nbsp; &nbsp; &nbsp; &nbsp; } else if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for i, c := range rb[:n] {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b[i+ttl] = decodeRot13(c)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ttl += n&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return ttl, err}在这一行:&nbsp; &nbsp; &nbsp; &nbsp; n, err := rr.r.Read(rb) // <-- and this 'err' are different由于:=分配,会创建一个新的实例err,它会隐藏在更高范围内定义的实例。这意味着当您退出 for 循环时,该版本的err不可用,并且nil使用设置为 的更高范围的版本。这就是为什么return ttl, err与相同return ttl, nil,又完全不同的原因return ttl, io.EOF。
打开App,查看更多内容
随时随地看视频慕课网APP