实现 io.Reader 时,无限循环中 break 与 return 的不同行为

我正在参加正式的巡回演出。今天,我在做rot13reader 练习时遇到了一些奇怪的事情。


问题是当我使用break而不是return ttl, io.EOF,程序进入无限循环。但是,据我所知,在这个程序中,应该没有区别break或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)

}



胡说叔叔
浏览 89回答 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

相关分类

Go