第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

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

ResponseWriter.Write 和 io.WriteString 有什么區(qū)別?

ResponseWriter.Write 和 io.WriteString 有什么區(qū)別?

Go
蕭十郎 2022-01-17 18:25:18
我見過三種將內(nèi)容寫入 HTTP 響應的方法:func Handler(w http.ResponseWriter, req *http.Request) {    io.WriteString(w, "blabla.\n")}和:func Handler(w http.ResponseWriter, r *http.Request) {    w.Write([]byte("blabla\n"))}還有:fmt.Fprintf(w, "blabla")他們之間有什么區(qū)別?首選使用哪一個?
查看完整描述

2 回答

?
慕斯709654

TA貢獻1840條經(jīng)驗 獲得超5個贊

io.Writer

輸出流表示您可以向其寫入字節(jié)序列的目標。io.Writer在 Go 中,這是由通用接口捕獲的:


type Writer interface {

    Write(p []byte) (n int, err error)

}

具有這種單一Write()方法的所有內(nèi)容都可以用作輸出,例如磁盤上的文件 ( os.File)、網(wǎng)絡連接 ( net.Conn) 或內(nèi)存緩沖區(qū) ( bytes.Buffer)。


http.ResponseWriter用來配置HTTP響應和發(fā)送數(shù)據(jù)給客戶端的也是這樣一個,io.Writer你要發(fā)送的數(shù)據(jù)(響應體)是通過調(diào)用組裝的(不一定只有一次)ResponseWriter.Write()(這是實現(xiàn)通用的io.Writer) . 這是您對http.ResponseWriter接口實現(xiàn)的唯一保證(關于發(fā)送主體)。


WriteString()

現(xiàn)在繼續(xù)WriteString()。通常我們想將文本數(shù)據(jù)寫入io.Writer. 是的,我們可以簡單地通過將 轉(zhuǎn)換string為 a來做到這一點[]byte,例如


w.Write([]byte("Hello"))

按預期工作。然而,這是一個非常頻繁的操作,因此io.StringWriter接口捕獲了一個“普遍”接受的方法(從Go 1.12開始可用,在此之前它未被導出):


type StringWriter interface {

    WriteString(s string) (n int, err error)

}

此方法提供了寫入string值而不是的可能性[]byte。所以如果某些東西(也實現(xiàn)了io.Writer)實現(xiàn)了這個方法,你可以簡單地傳遞string值而無需[]byte轉(zhuǎn)換。這似乎是對代碼的輕微簡化,但不僅如此。將 a 轉(zhuǎn)換string為[]byte必須復制string內(nèi)容(因為string值在 Go 中是不可變的,請在此處閱讀有關它的更多信息:golang: []byte(string) vs []byte(*string)),因此會產(chǎn)生一些開銷如果string“更大”和/或您必須多次執(zhí)行此操作,則很明顯。


根據(jù) a 的性質(zhì)和實現(xiàn)細節(jié),io.Writer可以編寫 a 的內(nèi)容string而不將其轉(zhuǎn)換為[]byte,從而避免上述開銷。


例如,如果 anio.Writer是寫入內(nèi)存緩沖區(qū)的東西(bytes.Buffer就是這樣一個例子),它可以利用內(nèi)置copy()函數(shù):


復制內(nèi)置函數(shù)將元素從源切片復制到目標切片。(作為一種特殊情況,它還將字節(jié)從字符串復制到字節(jié)片。)


可copy()用于將 a 的內(nèi)容(字節(jié))復制string到 a[]byte而無需將 轉(zhuǎn)換string為[]byte,例如:


buf := make([]byte, 100)

copy(buf, "Hello")

現(xiàn)在有一個“實用程序”函數(shù)io.WriteString()可以將 astring寫入io.Writer. 但它首先檢查傳遞的(動態(tài)類型)io.Writer是否有WriteString()方法,如果有,將使用該方法(其實現(xiàn)可能更有效)。如果傳遞io.Writer的沒有這樣的方法,那么一般的convert-to-byte-slice-and-write-that方法將被用作“后備”。


您可能認為這WriteString()只會在內(nèi)存緩沖區(qū)的情況下占優(yōu)勢,但事實并非如此。Web 請求的響應也經(jīng)常被緩沖(使用內(nèi)存緩沖區(qū)),因此它也可以提高性能http.ResponseWriter。如果您查看 : 的實現(xiàn),http.ResponseWriter它是未導出的類型http.response(server.go當前第 308 行),它確實實現(xiàn)了WriteString()(當前第 1212 行),所以它確實意味著改進。


總而言之,無論何時寫入string值,都建議使用它,io.WriteString()因為它可能更有效(更快)。


fmt.Fprintf()

您應該將此視為一種方便且簡單的方法,可以為要寫入的數(shù)據(jù)添加更多格式,以換取性能稍差。


因此fmt.Fprintf(),如果您想string以簡單的方式創(chuàng)建格式化,請使用,例如:


name := "Bob"

age := 23

fmt.Fprintf(w, "Hi, my name is %s and I'm %d years old.", name, age)

這將導致以下內(nèi)容string被寫入:


Hi, my name is Bob and I'm 23 years old.

您不能忘記的一件事:fmt.Fprintf()需要一個格式字符串,因此它將被預處理而不是按原樣寫入輸出。舉個簡單的例子:


fmt.Fprintf(w, "100 %%")

您希望"100 %%"將其寫入輸出(帶有 2 個%字符),但只會發(fā)送一個,因為格式字符串%是一個特殊字符,并且%%只會%在輸出中產(chǎn)生一個。


如果您只想string使用fmt包編寫一個,請使用fmt.Fprint()不需要格式string:


fmt.Fprint(w, "Hello")

使用該包的另一個好處fmt是您也可以編寫其他類型的值,而不僅僅是strings,例如


fmt.Fprint(w, 23, time.Now())

(當然,如何將任何值轉(zhuǎn)換為一個string- 并最終轉(zhuǎn)換為一系列字節(jié)的規(guī)則在fmt包的文檔中得到了很好的定義。)


對于“簡單”格式的輸出,fmt包可能沒問題。對于復雜的輸出文檔,請考慮使用text/template(對于一般文本)和html/template(只要輸出是 HTML)。


傳遞/移交 http.ResponseWriter

為了完整起見,我們應該提到,您希望作為 Web 響應發(fā)送的內(nèi)容通常是由支持“流式傳輸”結(jié)果的“某物”生成的。一個示例可能是從結(jié)構(gòu)或映射生成的 JSON 響應。


在這種情況下,如果它支持將結(jié)果寫入即時消息http.ResponseWriter,則傳遞/移交您的內(nèi)容通常會更有效。io.Writerio.Writer


一個很好的例子是生成 JSON 響應。當然,您可以使用 將一個對象編組為 JSON json.Marshal(),它會返回一個字節(jié)切片,您可以通過調(diào)用簡單地發(fā)送它ResponseWriter.Write()。


然而,讓json包知道你有一個io.Writer,并且最終你想將結(jié)果發(fā)送給它會更有效。這樣就不必首先在緩沖區(qū)中生成 JSON 文本,您只需將其寫入響應然后丟棄。json.Encoder您可以通過調(diào)用來創(chuàng)建一個新的json.NewEncoder(),您可以將您的http.ResponseWriteras傳遞給它io.Writer,然后調(diào)用Encoder.Encode()將直接將 JSON 結(jié)果寫入您的響應編寫器。


這里的一個缺點是,如果生成 JSON 響應失敗,您可能會收到部分發(fā)送/提交的響應,您無法收回。如果這對您來說是個問題,那么您除了在緩沖區(qū)中生成響應之外別無選擇,如果封送處理成功,那么您可以立即編寫完整的響應。


查看完整回答
反對 回復 2022-01-17
?
慕田峪7331174

TA貢獻1828條經(jīng)驗 獲得超13個贊

從這里(ResponseWriter)可以看出,它是一個帶有Write([]byte) (int, error)方法的接口。


所以 inio.WriteString和fmt.Fprintf兩者都將Writer作為第一個參數(shù),這也是一種接口包裝Write(p []byte) (n int, err error)方法


type Writer interface {

    Write(p []byte) (n int, err error)

}

因此,當您調(diào)用 io.WriteString(w,"blah") 時,請檢查此處


func WriteString(w Writer, s string) (n int, err error) {

  if sw, ok := w.(stringWriter); ok {

      return sw.WriteString(s)

  }

  return w.Write([]byte(s))

}

或 fmt.Fprintf(w, "blabla")在這里檢查


func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {

   p := newPrinter()

   p.doPrintf(format, a)

   n, err = w.Write(p.buf)

   p.free()

   return

}

您只是ResponseWriter在兩種方法中傳遞變量時間接調(diào)用 Write Method。


所以為什么不直接使用w.Write([]byte("blabla\n")). 我希望你得到你的答案。


PS:如果您想將其作為 JSON 響應發(fā)送,還有一種不同的使用方式。


json.NewEncoder(w).Encode(wrapper)

//Encode take interface as an argument. Wrapper can be:

//wrapper := SuccessResponseWrapper{Success:true, Data:data}


查看完整回答
反對 回復 2022-01-17
  • 2 回答
  • 0 關注
  • 648 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號