2016-07-26 42 views
0

有一个去旅游。我已经解决https://tour.golang.org/methods/23这样的:解决第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是正确的,回报显示正确的字符串调试输出权之前。但为什么没有输出到控制台?

回答

3

io.ReaderRead方法需要对提供给它的字节片进行操作。您正在阅读一个新的片段,并且从不修改原始片段。

只需使用b整个Read方法:

func (old_reader rot13Reader) Read(b []byte) (int, error) { 
    n, err := old_reader.r.Read(b) 
    rot13(b[:n]) 
    return n, err 
} 
+0

谢谢!输出参数是邪恶的:( – devmeow

+0

)如果你不把它作为参数传递,使用预先分配的读取缓冲区是很难的 – JimB

+0

这段代码不是很正确(尽管它可以用于' '''''''''''''''''''''''''''''''' ; rot13(b [:n]); return n,err'更准确 –

1

你永远在你的读者修改bio.ReaderRead函数的语义是将数据直接放入b的底层数组。

假设rot13()功能也就地修改,这将工作(编辑:我一直在努力,密切保持这个代码到你的版本,所以你可以看到什么变化更容易JimB的解决方案是一个更地道的解决方案这个问题):

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()):https://play.golang.org/p/vlbra-46zk

在一个侧面说明,从惯用perspect,old_reader是不正确的接收器名称(也不是old_len一个适当的变量名称)。 Go更喜欢短的接收者名称(例如rrdr在这种情况下),并且还喜欢camelcase来强调下划线(下划线实际上会触发golint警告)。

编辑2:您的代码更惯用的版本。保持相同的作用机制,只是把它清理一下。

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 
} 

由此看来,去除tmp字节片以及使用目的b直接导致JimB的惯用解决问题的方法。

编辑3:更新以解决保罗在评论中指出的问题。

+0

您应该使用早期返回模式来移除'els e'子句和主代码路径的缩进。没有必要分配额外的片,使用提供的片。如果您确实需要复制,请使用内置的“copy”复制字节而不是for循环。 – JimB

+0

是的,就像我在编辑中所说的那样,我故意尝试将其代码中的更改保持在必要的最低限度以使其功能更强大,因此差异更容易被看到。这是非常不习惯的Go。 – Kaedys

+0

这段代码与JimB有类似的问题:'Read'可能会返回n> 0,并且err!= nil(例如:err = io.EOF),当它发生时,会截断结果。 –

相关问题