亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Read 函數完成后,Go rot13Reader 緩沖區未更新

Read 函數完成后,Go rot13Reader 緩沖區未更新

Go
哆啦的時光機 2023-07-10 09:03:03
這是我使用 strings.Map 實現的練習(rot13 函數直接來自 golang 的文檔)。問題是在 Read 函數返回后緩沖區似乎沒有被修改。這是代碼:package mainimport (    "io"    "os"    "strings"    "fmt")type rot13Reader struct {    r io.Reader}func (reader *rot13Reader) Read(b []byte) (int, error) {    rot13 := func(r rune) rune {        switch {        case r >= 'A' && r <= 'Z':            return 'A' + (r-'A'+13)%26        case r >= 'a' && r <= 'z':            return 'a' + (r-'a'+13)%26        }        return r    }    n, err := reader.r.Read(b)    result := []byte(strings.Map(rot13, string(b)))    b = []byte(result)    fmt.Println(string(b))    return n, err}func main() {    s := strings.NewReader("Lbh penpxrq gur pbqr!")    r := rot13Reader{s}    io.Copy(os.Stdout, &r)}和輸出:You cracked the code!Lbh penpxrq gur pbqr!You cracked the code!顯然Read函數中緩沖區已經被修改了,但是返回后似乎不是這樣。如果我注釋掉fmt.Println(string(b)),輸出將是:Lbh penpxrq gur pbqr!關于讀者和作家有什么奇怪的事情我應該知道嗎?
查看完整描述

2 回答

?
滄海一幻覺

TA貢獻1824條經驗 獲得超5個贊

在 Go 中,所有參數都按值傳遞,就像通過分配給參數或接收者(淺拷貝)一樣。


在 Go 中,切片的實現為


type slice struct {

? ? array unsafe.Pointer

? ? len? ?int

? ? cap? ?int

}

當切片按值傳遞時,返回后,您將看不到對字段副本所做的任何更改struct。您只會看到底層數組元素的任何更改。


在您的情況下,您將覆蓋b( array, cap, len) 副本。


b = []byte(result)

當您返回時,該副本將被丟棄。


您想要做的是更改bs的元素array。


例如,


package main


import (

? ? "io"

? ? "os"

? ? "strings"

)


func rot13(b byte) byte {

? ? switch {

? ? case b >= 'A' && b <= 'Z':

? ? ? ? return 'A' + (b-'A'+13)%26

? ? case b >= 'a' && b <= 'z':

? ? ? ? return 'a' + (b-'a'+13)%26

? ? }

? ? return b

}


type rot13Reader struct {

? ? r io.Reader

}


func (reader *rot13Reader) Read(b []byte) (int, error) {

? ? n, err := reader.r.Read(b)

? ? b = b[:n]

? ? for i := range b {

? ? ? ? b[i] = rot13(b[i])

? ? }

? ? return n, err

}


func main() {

? ? s := strings.NewReader("Lbh penpxrq gur pbqr!")

? ? r := rot13Reader{s}

? ? io.Copy(os.Stdout, &r)

}


查看完整回答
反對 回復 2023-07-10
?
烙印99

TA貢獻1829條經驗 獲得超13個贊

我不太確定,所以請在服用下面的食物時加入幾粒到幾磅的鹽。


首先,您應該盡早添加錯誤檢查:


n, err := reader.r.Read(b)

if err != nil && err == io.EOF {

? ? fmt.Printf("\n%s, %d bytes read", err, n)

? ? return n, err

}

添加后,輸出就是您所期望的:


You cracked the code!

Lbh penpxrq gur pbqr!

EOF, 0 bytes read

這里的原因是讀者應該返回 io.EOF,以防沒有任何內容可供閱讀。


那么你為什么會經歷上述奇怪的行為呢?快速瀏覽一下源代碼就會io.Copy發現,b分配一次并重用。但由于b未修改(未讀取任何字節)并且您訪問它以從中讀取,因此它仍然保留與以前相同的值。不過,我認為,根據最小意外原則,如果沒有讀到任何內容,底層io.Reader應該是清晰的。b



查看完整回答
反對 回復 2023-07-10
  • 2 回答
  • 0 關注
  • 185 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號