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

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

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

Go
肥皂起泡泡 2023-08-07 19:04:28
我正在经历正式的旅行。问题是当我使用break而不是 时return ttl, io.EOF,程序会进入无限循环。但是,据我所知,在这个程序中,与breakor应该没有区别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贡献1818条经验 获得超8个赞

观察到的行为是由于变量阴影造成的:


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。


查看完整回答
反对 回复 2023-08-07
  • 1 回答
  • 0 关注
  • 112 浏览
慕课专栏
更多

添加回答

举报

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