为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
胡说叔叔 2022-04-20 20:52:30
我正在参加正式的巡回演出。今天,我在做rot13reader 练习时遇到了一些奇怪的事情。问题是当我使用break而不是return ttl, io.EOF,程序进入无限循环。但是,据我所知,在这个程序中,应该没有区别break或return ttl, io.EOF因为如果是break,下一行将return ttl, err在方法的末尾,Read()与return ttl, io.EOF.我想知道为什么。与 Go 如何处理 io.Reader 接口及其实现的底层机制有关吗?这是代码。package mainimport (    "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)}
查看完整描述

1 回答

?
扬帆大鱼

TA贡献1799条经验 获得超9个赞

观察到的行为是由于可变阴影:


func (rr *rot13Reader) Read(b []byte) (n int, err error) { // <-- this 'err'

    rb := make([]byte, 8)

    var ttl int

    for {

        n, err := rr.r.Read(rb) // <-- and this 'err' are different

        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

}

在这条线上:


        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。


查看完整回答
反对 回复 2022-04-20
  • 1 回答
  • 0 关注
  • 88 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信