为什么使用裸返回(naked return)和普通返回会给我不同的结果?

huangapple go评论119阅读模式
英文:

Why using naked return and the normal return give me different results?

问题

我正在使用Golang tour进行实验,我想知道为什么使用裸返回(naked return)会给我正确的结果,而普通的返回却不会。这是我遇到问题的练习链接:https://tour.golang.org/methods/12。

目标是创建一个可以解密rot13的读取器,而rot13函数已经经过测试。

func (r rot13Reader) Read(b []byte) (n int, err error) {
    n, err =  r.r.Read(b)
    for i, v := range b {
        b[i] = rot13(v)
    }
    return
}

上面的代码给出了正确的结果。

func (r rot13Reader) Read(b []byte) (int, error) {
    for i, v := range b {
        b[i] = rot13(v)
    }
    return r.r.Read(b)
}

而这段代码却没有改变输入流。

有人能解释一下为什么吗?提前谢谢你。

英文:

I'm playing around with Golang tour and I wonder why using naked return give me the correct result but the normal one doesn't. This is the exercise that I have this problem https://tour.golang.org/methods/12.

The objective is to create a reader that can decipher rot13. and the rot13 function is already tested.

func (r rot13Reader) Read(b []byte) (n int, err error) {
    n, err =  r.r.Read(b)
    for i, v := range b {
	    b[i] = rot13(v)
    }
    return
}

The code above give me the correct result.

func (r rot13Reader) Read(b []byte) (int, error) {
	for i, v := range b {
	b[i] = rot13(v)
	}
    return r.r.Read(b)
}

And this doesn't change anything from the input stream.

Could anybody explain why? Thank you in advance.

答案1

得分: 3

Read()操作会改变输入数组b。在第二个示例中,Read()操作覆盖了rot13()操作。此外,在任何数据被读入数组之前,rot13()操作就已经执行了,所以你可能在垃圾数据上执行了rot13()操作。

如果你希望第二个示例起作用,你需要编写类似下面这样的代码:

func (r rot13Reader) Read(b []byte) (int, error) {
    n, err := r.r.Read(b)
    for i, v := range b {
        b[i] = rot13(v)
    }
    return n, err 
}
英文:

The Read() operation mutates the input array b. In the second example the rot13() operations are overwritten by the Read() operation. Furthermore, the rot13() operation is performed before any data has been read into the array, so you're probably doing rot13() on garbage data.

If you wanted the second example to work you'd need to write something like this:

func (r rot13Reader) Read(b []byte) (int, error) {
    n, err := r.r.Read(b)
    for i, v := range b {
    b[i] = rot13(v)
    }
    return n, err 
}

答案2

得分: 3

这不是返回值的问题,而是在第一种情况下,你在转换数据之前读取了数据,而在第二种情况下,你先将垃圾数据转换为缓冲区,然后再读取数据(并且只是简单地传递从底层读取器读取的内容)。

虽然这不是必需的,但我建议你每次只转换已读取的部分,而不是整个缓冲区,即将你的第一个示例从for i, v := range b改为for i, v := range b[:n]。这是因为io.Read调用无法修改切片b的长度,只能修改其内容。

请查看io.Reader的文档,它应该能给你一些关于这个接口如何工作的更多想法。

英文:

It's not a problem with returns, but in the first case you're reading the data in before transforming it and in the second case you're transforming junk in a buffer and only then reading in the data (and simply passing what has been read from the underlying reader).

While this is not required for correctness, I'd suggest you don't transform the whole buffer every time, but only the portion that has been read, i.e. changing your first example from for i, v := range b to for i, v := range b[:n]. That's because io.Read call is not able to modify length of slice b, but just its content.

Take a look at the documentation of io.Reader, it should give you some more idea on how this interface is expected to work.

huangapple
  • 本文由 发表于 2015年6月18日 18:10:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/30912457.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定