2016-07-26 4 views
0

Es gibt eine Go-Tour. Ich habe https://tour.golang.org/methods/23 wie folgt gelöst:Was ist los mit der Lösung für die 23. Aufgabe der Tour?

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) 
} 

Wo rot13 korrekt ist und Debug-Ausgabe direkt vor der Rückkehr zeigt korrekte Zeichenfolge. Aber warum gibt es keine Ausgabe auf der Konsole?

Antwort

3

Die Read-Methode für eine io.Reader muss auf der Byte-Schicht arbeiten, die ihr zur Verfügung gestellt wird. Sie lesen in ein neues Segment und ändern das Original nie.

Verwenden Sie einfach b während der Read-Methode:

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

Danke! Ausgabeparameter ist böse :( – devmeow

+0

Es ist ein bisschen schwierig, einen vorher zugewiesenen Lesepuffer zu verwenden, wenn Sie es nicht als Parameter übergeben. – JimB

+0

Dieser Code ist nicht ganz richtig (obwohl es für ein 'arbeitet strings.Reader ') -' Read' kann einen Fehler und ein von Null verschiedenes 'n' zurückgeben, und wenn dies der Fall ist, dekodiert das Dekodiergerät das Ergebnis nicht.' n, err: = old_reader.r.Read (b) ; rot13 (b [: n]); return n, err "ist genauer. –

1

Sie nie b in Ihrem Leser zu modifizieren. Die Semantik von io.Reader 's Read Funktion ist, dass Sie die Daten in b' s zugrunde liegenden Array direkt setzen.

die rot13() Funktion auch an Ort und Stelle ändert Unter der Annahme, dies funktionieren wird (bearbeitet:. Ich habe versucht, auf Ihre Version diesen Code zu halten, schließen, so können Sie sehen, was leichter geändert hat JimB-Lösung ist eine idiomatische Lösung dieses Problem):

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 
} 

Beispiel (mit stubbed rot13()): https://play.golang.org/p/vlbra-46zk

Auf einer Seite zur Kenntnis, von einer idiomatischen perspect ist old_reader kein richtiger Empfängername (noch ist old_len ein richtiger Variablenname). Go bevorzugt kurze Empfänger-Namen (wie r oder rdr in diesem Fall), und auch Camelcase zu Unterstrichen bevorzugen (Unterstriche werden tatsächlich eine golint Warnung ausgelöst).

Edit2: Eine idiomatische Version Ihres Codes. Behielt den gleichen Mechanismus der Aktion, nur ein wenig aufgeräumt.

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 
} 

Daraus die tmp Byte Scheibe zu entfernen und mit dem Ziel b direkt in JimB der idiomatische Lösung des Problems führt.

Edit3: Aktualisiert, um das Problem zu beheben, auf das Paul in Kommentaren hingewiesen hat.

+0

Sie sollten ein frühes Rückkehrmuster verwenden, um die "els" zu entfernen e'-Klausel und Einzug des Hauptcodepfades. Sie müssen das zusätzliche Slice nicht zuweisen, sondern das bereitgestellte Slice verwenden.Wenn Sie kopieren müssen, verwenden Sie die eingebaute 'copy'-Funktion, um Bytes anstatt einer for-Schleife zu kopieren. – JimB

+0

Ja, wie ich in der Bearbeitung gesagt habe, habe ich absichtlich versucht, die Änderungen an seinem Code auf das notwendige Minimum zu beschränken, damit es funktioniert, so dass die Unterschiede leichter zu sehen sind. Es ist sehr nicht ideal idiomatische Go. – Kaedys

+0

Dieser Code hat ein ähnliches Problem wie die von JimB: 'Read' kann n> 0 und err! = Nil (zB: err = io.EOF) zurückgeben, und wenn dies der Fall ist, schneidet man das Ergebnis ab. –