有一个游览。我已经解决了https://tour.golang.org/methods/23这样的问题:
func (old_reader rot13Reader) Read(b []byte) (int, error) {
const LEN int = 1024
tmp_bytes := make([]byte, LEN)
old_len, err := old_reader.r.Read(tmp_bytes)
if err == nil {
tmp_bytes = tmp_bytes[:old_len]
rot13(tmp_bytes)
return len(tmp_bytes), nil
} else {
return 0, err
}
}
func main() {
s := strings.NewReader("Lbh penpxrq gur pbqr!")
r := rot13Reader{s}
io.Copy(os.Stdout, &r)
}
rot13
正确且返回前调试输出显示正确的字符串。但为什么控制台没有输出?
答案 0 :(得分:3)
Read
的{{1}}方法需要对提供给它的字节切片进行操作。你正在阅读一个新的切片,而不是修改原始切片。
在整个Read方法中使用io.Reader
:
b
答案 1 :(得分:1)
您永远不会在读者中修改ValueError: dictionary update sequence element #0 has length 6; 2 is required
。 b
的{{1}}函数的语义是您将数据直接放入io.Reader
的基础数组中。
假设Read
功能也就地修改,这将有效(编辑:我试图让这些代码保持接近您的版本,这样您就可以更容易地看到更改的内容。 JimB的解决方案是解决这个问题的更惯用的方法):
b
示例(带有存根rot13()
):https://play.golang.org/p/vlbra-46zk
另一方面,从惯用的角度来看,func (old_reader rot13Reader) Read(b []byte) (int, error) {
tmp_bytes := make([]byte, len(b))
old_len, err := old_reader.r.Read(tmp_bytes)
tmp_bytes = tmp_bytes[:old_len]
rot13(tmp_bytes)
for i := range tmp_bytes {
b[i] = tmp_bytes[i]
}
return old_len, err
}
不是一个合适的接收者名称(rot13()
也不是一个合适的变量名称)。 Go更喜欢短接收者名称(在这种情况下比较old_reader
或old_len
),也更喜欢camelcase到下划线(下划线实际上会发出r
警告)。
Edit2 :更加惯用的代码版本。保持相同的行动机制,只是稍微清理了一下。
rdr
由此,删除golint
字节切片并使用目标func (rdr rot13Reader) Read(b []byte) (int, error) {
tmp := make([]byte, len(b))
n, err := rdr.r.Read(tmp)
tmp = tmp[:n]
rot13(tmp)
for i := range tmp {
b[i] = tmp[i]
}
return n, err
}
直接导致JimB解决问题的惯用方法。
Edit3 :已更新以解决Paul在评论中指出的问题。