自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Go 1.4 相比 Go 1.3 有哪些值得注意的改動?

開發(fā) 前端
Go 1.4 的一個里程碑式的改動是將運(yùn)行時的絕大部分代碼從 C 語言和少量匯編遷移到了 Go 語言實現(xiàn)。這次重構(gòu)雖然龐大,但其設(shè)計目標(biāo)是對用戶程序在語義上透明,同時帶來了幾個關(guān)鍵的技術(shù)進(jìn)步和性能優(yōu)化。

https://go.dev/doc/go1.4

Go 1.4 值得關(guān)注的改動:

  • for-range 循環(huán)語法更加靈活。在 Go 1.4 之前,即使你只關(guān)心循環(huán)迭代本身,而不使用循環(huán)變量(index/value),也必須顯式地寫一個變量(通常是空白標(biāo)識符 _),如 for _ = range x {}。Go 1.4 允許省略循環(huán)變量,可以直接寫成 for range x {}。雖然這種場景不常見,但在需要時能讓代碼更簡潔。
  • 修復(fù)了編譯器允許對指向指針的指針(pointer-to-pointer)類型直接調(diào)用方法的問題。Go 語言規(guī)范允許對指針類型的值進(jìn)行方法調(diào)用時自動插入一次解引用(dereference),但只允許一次。例如,若類型 T 有方法 M(),t 是 *T 類型,則 t.M() 合法。然而,Go 1.4 之前的編譯器錯誤地接受了對 **T 類型的變量 x 直接調(diào)用 x.M(),這相當(dāng)于進(jìn)行了兩次解引用,違反了規(guī)范。Go 1.4 禁止了這種調(diào)用,這是一個破壞性變更(breaking change),但預(yù)計實際受影響的代碼非常少。
  • 擴(kuò)展了對新操作系統(tǒng)和架構(gòu)的支持。Go 1.4 引入了對在 ARM 處理器上運(yùn)行 Android 操作系統(tǒng)的實驗性支持,可以構(gòu)建 Go 應(yīng)用或供 Android 應(yīng)用調(diào)用的 .so 庫。此外,還增加了對 ARM 上的 Native Client (NaCl) 以及 AMD64 架構(gòu)上的 Plan 9 操作系統(tǒng)的支持。
  • Go 運(yùn)行時(runtime)的大部分實現(xiàn)從 C 語言遷移到了 Go 語言。這次重構(gòu)使得垃圾回收器(garbage collector)能夠精確地掃描運(yùn)行時自身的棧,實現(xiàn)了完全精確的垃圾回收,從而減少了內(nèi)存占用。同時,棧(stack)的實現(xiàn)改為連續(xù)棧(contiguous stacks),解決了棧熱分裂(hot split)問題,并為 Go 1.5 計劃中的并發(fā)垃圾回收(concurrent garbage collector)引入了寫屏障(write barrier)機(jī)制。
  • 引入了 internal 包機(jī)制和規(guī)范導(dǎo)入路徑(canonical import path)檢查。internal 包提供了一種方式來定義只能被特定代碼樹內(nèi)部導(dǎo)入的包,增強(qiáng)了大型項目代碼的封裝性。規(guī)范導(dǎo)入路徑通過在 package 聲明行添加特定注釋來指定唯一的導(dǎo)入路徑,防止同一個包被通過不同路徑導(dǎo)入,提高了代碼的可維護(hù)性。
  • 修復(fù)了 bufio.Scanner 在處理文件結(jié)束符(EOF)時的行為。此修復(fù)確保了即使在輸入數(shù)據(jù)耗盡時,自定義的分割函數(shù)(split function)也會在文件結(jié)束符(EOF)處被最后調(diào)用一次。這使得分割函數(shù)有機(jī)會按預(yù)期生成一個最終的空令牌(token),但也可能影響依賴舊有錯誤行為的自定義分割函數(shù)。

下面是一些值得展開的討論:

Runtime 重構(gòu)與核心變化

Go 1.4 的一個里程碑式的改動是將運(yùn)行時的絕大部分代碼從 C 語言和少量匯編遷移到了 Go 語言實現(xiàn)。這次重構(gòu)雖然龐大,但其設(shè)計目標(biāo)是對用戶程序在語義上透明,同時帶來了幾個關(guān)鍵的技術(shù)進(jìn)步和性能優(yōu)化。

首先,這次遷移使得 Go 1.4 的垃圾回收器(GC)能夠?qū)崿F(xiàn) 完全精確(fully precise) 的內(nèi)存管理。精確 GC 意味著回收器能夠準(zhǔn)確地識別內(nèi)存中哪些是活躍的指針,哪些不是。在此之前,GC 可能存在保守掃描(conservative scanning)的情況,即把一些非指針的數(shù)據(jù)(比如整數(shù))誤判為指針,導(dǎo)致這些數(shù)據(jù)引用的內(nèi)存無法被回收(稱為“假陽性”)。精確 GC 消除了這種假陽性,能夠更有效地回收不再使用的內(nèi)存,根據(jù)官方文檔,這使得程序的堆(heap)內(nèi)存占用相比之前版本減少了 10%-30%。

其次,Goroutine 的 棧(stack)實現(xiàn)從分段棧(segmented stacks)改為了連續(xù)棧(contiguous stacks)。這一點(diǎn)在 Go 1.3 中也提及了:每個 Goroutine 的棧由多個小的、不連續(xù)的內(nèi)存塊(段)組成。當(dāng)一個函數(shù)調(diào)用需要的棧空間超過當(dāng)前段的剩余空間時,會觸發(fā)“棧分裂”,分配一個新的棧段。這種機(jī)制的主要缺點(diǎn)是 “棧熱分裂(hot split)” 問題:如果一個函數(shù)調(diào)用頻繁地發(fā)生在棧段即將耗盡的邊界處,就會導(dǎo)致在循環(huán)中頻繁地分配和釋放新的棧段,帶來顯著的性能開銷,且性能表現(xiàn)難以預(yù)測。

Go 1.4 采用的連續(xù)棧則為每個 Goroutine 分配一塊連續(xù)的內(nèi)存作為其棧。當(dāng)??臻g不足時,運(yùn)行時會分配一塊更大的新連續(xù)內(nèi)存,將舊棧的全部內(nèi)容(所有活躍的棧幀)復(fù)制到新棧,并更新棧內(nèi)部指向自身的指針。這個過程依賴于 Go 的逃逸分析(escape analysis)保證,即指向棧上數(shù)據(jù)的指針通常只存在于棧自身內(nèi)部(向下傳遞),使得復(fù)制和指針更新成為可能。雖然復(fù)制棧有成本,但它是一次性的(直到下一次增長),避免了熱分裂問題,使得性能更加穩(wěn)定和可預(yù)測。正如 Go 1.3 的設(shè)計文檔(Contiguous Stacks design document)中所討論的,這種方式解決了分段棧的核心痛點(diǎn)。

由于連續(xù)棧消除了熱分裂帶來的性能懲罰,Goroutine 的 初始棧大小得以顯著減小。Go 1.4 將 Goroutine 的默認(rèn)初始棧大小從 8192 字節(jié)(8KB)降低到了 2048 字節(jié)(2KB),這有助于在創(chuàng)建大量 Goroutine 時節(jié)省內(nèi)存。

再次,為了給 Go 1.5 計劃引入的 并發(fā)垃圾回收(concurrent garbage collector) 做準(zhǔn)備,Go 1.4 引入了 寫屏障(write barrier)。寫屏障是一種機(jī)制,它將程序中對堆(heap)上指針值的寫入操作從直接的內(nèi)存寫入,改為通過一個運(yùn)行時函數(shù)調(diào)用來完成。在 Go 1.4 中,這個屏障本身可能還沒有太多實際的 GC 協(xié)調(diào)工作,主要是為了測試其對編譯器和程序性能的影響。在 Go 1.5 中,當(dāng) GC 與用戶 Goroutine 并發(fā)運(yùn)行時,寫屏障將允許 GC 介入和記錄這些指針寫入操作,以確保 GC 的正確性(例如,防止 GC 錯誤地回收被用戶代碼新近引用的對象)。

此外,接口值(interface value)的內(nèi)部實現(xiàn)也發(fā)生了改變。在早期版本中,接口值內(nèi)部根據(jù)存儲的具體類型(concrete type)是持有指向數(shù)據(jù)的指針,還是直接存儲單字大小的標(biāo)量值(如小整數(shù))。這種雙重表示給 GC 處理帶來了復(fù)雜性。從 Go 1.4 開始,接口值 始終 存儲一個指向?qū)嶋H數(shù)據(jù)的指針。對于大多數(shù)情況(接口通常存儲指針類型或較大的結(jié)構(gòu)體),這個改變影響很小。但對于將小整數(shù)等非指針類型的值存入接口的場景,現(xiàn)在會觸發(fā)一次額外的堆內(nèi)存分配,以存儲這個值并讓接口持有指向它的指針。

最后,關(guān)于 無效指針檢查。Go 1.3 引入了一個運(yùn)行時檢查,如果發(fā)現(xiàn)內(nèi)存中本應(yīng)是指針的位置包含明顯無效的值(如 3),程序會崩潰。這旨在幫助發(fā)現(xiàn)將整數(shù)錯誤地當(dāng)作指針使用的 bug。然而,一些(不規(guī)范的)代碼確實可能這樣做。為了提供一個過渡方案,Go 1.4 增加了 GODEBUG 環(huán)境變量 invalidptr=0。設(shè)置該變量可以禁用這種崩潰。但官方強(qiáng)調(diào)這只是一個臨時解決方法,不能保證未來版本會繼續(xù)支持,正確的做法是修改代碼,避免將整數(shù)和指針混用(類型別名)。

Internal 包:增強(qiáng)封裝性

Go 語言通過導(dǎo)出(exported, 首字母大寫)和未導(dǎo)出(unexported, 首字母小寫)標(biāo)識符提供了基本的代碼封裝能力。對于一個獨(dú)立的包來說,這通常足夠了。但是,當(dāng)一個大型項目(比如一個復(fù)雜的庫或應(yīng)用程序)本身需要被拆分成多個內(nèi)部協(xié)作的包時,問題就出現(xiàn)了。如果這些內(nèi)部包之間需要共享一些公共函數(shù)或類型,按照 Go 的可見性規(guī)則,這些共享的標(biāo)識符必須是導(dǎo)出的(首字母大寫)。但這會導(dǎo)致一個不希望的副作用:這些本應(yīng)只在項目內(nèi)部使用的 API,也意外地暴露給了項目的最終用戶。外部用戶可能會開始依賴這些內(nèi)部實現(xiàn)細(xì)節(jié),使得項目維護(hù)者未來重構(gòu)或修改內(nèi)部結(jié)構(gòu)變得困難,因為需要考慮對這些“非官方”用戶的兼容性。

為了解決這種“要么全公開,要么全包內(nèi)私有”的二元限制,Go 1.4 引入了一個由 go 工具鏈強(qiáng)制執(zhí)行的約定: internal 包 。

核心規(guī)則:

如果一個目錄名為 internal,那么位于這個 internal 目錄(及其子目錄)下的所有包,只能被 直接包含 該 internal 目錄的 父目錄 及其 子樹 中的代碼所導(dǎo)入。任何處于這個父目錄樹之外的代碼都無法導(dǎo)入該 internal 包。

文件樹示例:

假設(shè)我們有如下的項目結(jié)構(gòu):

/home/user/
└── myproject/
    ├── go.mod
    ├── cmd/
    │   └── myapp/
    │       └── main.go       <- 可以導(dǎo)入 internal/util, *不能* 導(dǎo)入 pkg/internal/core
    ├── pkg/
    │   ├── api/
    │   │   └── handler.go    <- 可以導(dǎo)入 internal/util 和 pkg/internal/core
    │   └── internal/         <- 這是 pkg 目錄下的 internal
    │       └── core/
    │           └── core.go   <- 定義內(nèi)部核心功能
    ├── internal/             <- 這是項目根目錄下的 internal
    │   └── util/
    │       └── util.go       <- 定義項目范圍的內(nèi)部工具
    └── vendor/               <- (無關(guān))
    └── anotherpkg/           <- 一個與 pkg 平級的目錄
        └── service.go        <- *不能* 導(dǎo)入 internal/util 或 pkg/internal/core
/home/user/
└── otherproject/
    └── main.go               <- *不能* 導(dǎo)入 myproject/internal/util 或 myproject/pkg/internal/core

根據(jù)上述規(guī)則和示例:

  1. myproject/internal/util 包:
  • 它的父目錄是 myproject/。
  • 因此,只有 myproject/ 目錄及其所有子目錄中的代碼(如 myproject/cmd/myapp/main.go, myproject/pkg/api/handler.go)可以導(dǎo)入 myproject/internal/util。
  • myproject/anotherpkg/service.go 因為不在 myproject/ 的子樹中(雖然在同一個項目下,但 internal 的直接父級是 myproject,anotherpkg 與 internal 平級),所以不能導(dǎo)入它。
  • 外部項目 otherproject/main.go 顯然也不能導(dǎo)入。
  1. myproject/pkg/internal/core 包:
  • 它的父目錄是 myproject/pkg/。
  • 因此,只有 myproject/pkg/ 目錄及其所有子目錄中的代碼(如 myproject/pkg/api/handler.go)可以導(dǎo)入 myproject/pkg/internal/core。
  • 位于 myproject/cmd/myapp/main.go 的代碼,雖然也在 myproject 項目內(nèi),但它不屬于 myproject/pkg/ 的子樹,所以 不能 導(dǎo)入 myproject/pkg/internal/core。
  • 外部項目和 myproject/anotherpkg 同理,也不能導(dǎo)入。

總結(jié): internal 目錄就像一道屏障,它允許其“直系親屬”(父目錄及其后代)訪問內(nèi)部成員,但阻止了所有“外人”(包括同一項目中的非后代包以及其他項目)的訪問。

這個檢查是由 go build, go test 等 go 命令在編譯時強(qiáng)制執(zhí)行的。在 Go 1.4 中,此規(guī)則首先應(yīng)用于 Go 標(biāo)準(zhǔn)庫($GOROOT)自身的組織,從 Go 1.5 開始,該規(guī)則被推廣到所有用戶的 GOPATH 和后來的 Go Modules 項目中。

規(guī)范導(dǎo)入路徑:確保唯一性與可維護(hù)性

在 Go 中,開發(fā)者可以使用 go get 工具方便地獲取和安裝托管在公共服務(wù)(如 github.com)上的代碼。包的導(dǎo)入路徑通常就反映了其托管位置,例如 github.com/user/repo。然而,Go 也提供了一種機(jī)制,允許開發(fā)者設(shè)置 自定義導(dǎo)入路徑(custom/vanity import paths),比如使用自己的域名 mycompany.com/mylib,并通過在 mycompany.com/mylib 這個 URL 提供特定的 HTML <meta> 標(biāo)簽,將 go get 工具重定向到實際的代碼倉庫(例如 github.com/user/repo)。

這種自定義路徑很有用,它可以:

  • 為包提供一個穩(wěn)定的、與托管服務(wù)無關(guān)的名稱。即使未來將代碼庫從 GitHub 遷移到 GitLab,只要更新 mycompany.com/mylib 的重定向,使用者的導(dǎo)入路徑無需更改。
  • 支持使用 go 工具不直接識別的版本控制系統(tǒng)或服務(wù)器。

但這也帶來了一個問題:同一個包現(xiàn)在可能有兩個有效的導(dǎo)入路徑:自定義路徑 (mycompany.com/mylib) 和實際托管路徑 (github.com/user/repo)。這會導(dǎo)致:

  • 意外的重復(fù)導(dǎo)入:如果一個程序的不同部分不小心通過不同的路徑導(dǎo)入了同一個包,編譯器會認(rèn)為它們是兩個不同的包,導(dǎo)致代碼冗余,甚至可能因為狀態(tài)不共享而引發(fā) bug。
  • 更新問題:用戶可能一直使用非官方的托管路徑導(dǎo)入,如果包作者只維護(hù)自定義路徑的重定向,用戶可能無法及時獲知更新。
  • 破壞兼容性:如果包作者遷移了倉庫并更新了自定義路徑的重定向,那些仍然使用舊托管路徑的用戶代碼會直接編譯失敗。

為了解決這些問題,Go 1.4 引入了 規(guī)范導(dǎo)入路徑(canonical import path) 檢查機(jī)制。

工作方式: 包的作者可以在其源代碼文件的 package 聲明行的末尾添加一個特定格式的注釋,來聲明該包的 唯一 官方導(dǎo)入路徑。

語法:

package pdf // import "rsc.io/pdf"

或者使用塊注釋:

package pdf /* import "rsc.io/pdf" */

效果: 當(dāng) go 命令(如 go build, go install)編譯一個導(dǎo)入了帶有此種注釋的包時,它會檢查導(dǎo)入時使用的路徑是否與注釋中聲明的規(guī)范路徑完全一致。如果不一致,go 命令將 拒絕編譯 導(dǎo)入方代碼。

示例: 如果 rsc.io/pdf 包中包含了 package pdf // import "rsc.io/pdf" 的注釋,那么任何試圖 import "github.com/rsc/pdf" 的代碼在編譯時都會失敗。這強(qiáng)制所有使用者都必須使用 rsc.io/pdf 這個規(guī)范路徑。

重要提示: 這個檢查是在 構(gòu)建時(build time) 進(jìn)行的,而不是在 go get 下載時。這意味著,如果 go get github.com/rsc/pdf 成功下載了代碼,但在后續(xù)編譯時因為規(guī)范路徑檢查失敗,你需要手動刪除本地 GOPATH 或 Go Modules 緩存中通過錯誤路徑下載的包副本。

相關(guān)改進(jìn): 為了配合這個特性,go get -u(更新包)命令也增加了一項檢查:它會驗證本地已下載包的遠(yuǎn)程倉庫地址是否與其自定義導(dǎo)入路徑解析出的地址一致。如果包的實際托管位置自上次下載后發(fā)生了改變(可能意味著倉庫遷移),go get -u 會失敗,防止意外更新??梢允褂眯碌?nbsp;-f 標(biāo)志來強(qiáng)制覆蓋此檢查。

子倉庫路徑遷移: Go 官方也借此機(jī)會宣布,其下的子倉庫(如 code.google.com/p/go.tools 等)將統(tǒng)一使用 golang.org/x/ 前綴的自定義導(dǎo)入路徑(如 golang.org/x/tools),并計劃在未來(約 2015 年 6 月 1 日)為這些包添加規(guī)范導(dǎo)入路徑注釋。屆時,使用 Go 1.4 及更高版本的用戶如果還在使用舊的 code.google.com 路徑,編譯將會失敗。官方強(qiáng)烈建議所有開發(fā)者更新其代碼,改用新的 golang.org/x/ 路徑導(dǎo)入這些子倉庫包。好消息是,舊版本的 Go (Go 1.0+) 也能識別和使用新的 golang.org/x/ 路徑,所以更新導(dǎo)入路徑不會破壞對舊 Go 版本的兼容性。

bufio.Scanner EOF 行為變更

bufio.Scanner 是 Go 標(biāo)準(zhǔn)庫中用于方便地讀取輸入流(如文件、網(wǎng)絡(luò)連接或字符串)并將其分割成一個個“令牌(token)”的工具。默認(rèn)情況下,它可以按行或按 UTF-8 單詞分割,但它也允許用戶提供自定義的分割邏輯,即 分割函數(shù)(SplitFunc)。

SplitFunc 的類型簽名是:

type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)
  • data: 當(dāng)前 Scanner 緩沖區(qū)中剩余未處理的數(shù)據(jù)。
  • atEOF: 一個布爾值,指示是否已經(jīng)到達(dá)輸入流的末尾(End Of File)。**true 表示底層 reader 不會再提供更多數(shù)據(jù)了**。
  • advance: SplitFunc 應(yīng)該告訴 Scanner 消耗掉 data 中的多少字節(jié)。
  • token: 這次調(diào)用找到的令牌。如果還沒找到完整的令牌,可以返回 nil。
  • err: 如果遇到錯誤,返回非 nil 的 error。

Go 1.4 之前的行為與問題:

在 Go 1.4 之前,Scanner 在處理 EOF 時存在一個微妙的問題。當(dāng)輸入流恰好在最后一個有效令牌的分隔符之后結(jié)束時,或者當(dāng)輸入流為空時,SplitFunc 可能無法可靠地生成一個預(yù)期的、位于流末尾的 空令牌。文檔承諾了可以做到這一點(diǎn),但實際行為有時不一致。

Go 1.4 的修復(fù)與新行為:

Go 1.4 修復(fù)了這個問題。現(xiàn)在的行為更加明確和可靠:**當(dāng)輸入流耗盡后,SplitFunc 保證會被最后調(diào)用一次,并且這次調(diào)用時 atEOF 參數(shù)為 true**。這次調(diào)用給予了 SplitFunc 處理輸入結(jié)束狀態(tài)的最后機(jī)會,使其能夠根據(jù)需要生成最后一個令牌,即使這個令牌是空的。

代碼示例:

假設(shè)我們要實現(xiàn)一個按逗號分割的 SplitFunc,并且希望正確處理末尾的空字段(例如 "a,b," 應(yīng)該產(chǎn)生三個令牌:"a", "b", "")。下面是一個能體現(xiàn) Go 1.4 行為的實現(xiàn):

package main

import (
"bufio"
"bytes"
"fmt"
"strings"
)

// customSplit: 按逗號分割,能處理末尾空字段
func customSplit(data []byte, atEOF bool) (advance int, token []byte, err error) {
// 查找第一個逗號
if i := bytes.IndexByte(data, ','); i >= 0 {
// 找到逗號,返回逗號之前的部分
return i + 1, data[:i], nil
 }

// 沒有找到逗號
if atEOF {
// 如果是 EOF,無論 data 是否為空,都認(rèn)為掃描結(jié)束。
        // data 中剩余的部分(如果非空)是最后一個 token。
iflen(data) == 0 {
   // 沒有剩余數(shù)據(jù)且已達(dá) EOF,停止掃描。
   return0, nil, nil
  }
// 如果有剩余數(shù)據(jù),返回它作為最后一個 token。
returnlen(data), data, nil
 }

// 沒有逗號,也沒到 EOF,請求 Scanner 讀取更多數(shù)據(jù)
return0, nil, nil
}

func main() {
 inputs := []string{
"a,b,c",     // 標(biāo)準(zhǔn)情況
"a,b,",      // 末尾有逗號,應(yīng)有空字段
"",          // 空輸入
"a",         // 單個字段
",a,b",      // 開頭有逗號,應(yīng)有空字段
"a,,b",      // 中間有逗號,應(yīng)有空字段
 }

for _, input := range inputs {
  fmt.Printf("Scanning input: %q\n", input)
  scanner := bufio.NewScanner(strings.NewReader(input))
  scanner.Split(customSplit)

  count := 0
for scanner.Scan() {
   count++
   fmt.Printf("  Token %d: %q\n", count, scanner.Text())
  }

if err := scanner.Err(); err != nil {
   fmt.Printf("  Error during scan: %v\n", err)
  }
  fmt.Println("---")
 }
}

預(yù)期輸出 (Go 1.4 及以后):

Scanning input: "a,b,c"
  Token 1: "a"
  Token 2: "b"
  Token 3: "c"
---
Scanning input: "a,b,"
  Token 1: "a"
  Token 2: "b"
  Token 3: ""
---
Scanning input: ""
---
Scanning input: "a"
  Token 1: "a"
---
Scanning input: ",a,b"
  Token 1: ""
  Token 2: "a"
  Token 3: "b"
---
Scanning input: "a,,b"
  Token 1: "a"
  Token 2: ""
  Token 3: "b"
---

主要的區(qū)別在于輸入 "a,b,"。在 Go 1.4 之前的版本中,由于 bufio.Scanner 的 bug,最后一個由結(jié)尾逗號產(chǎn)生的空令牌 "" 無法被正確掃描出來,導(dǎo)致輸出只有 "a" 和 "b"。而 Go 1.4 修復(fù)了這個 bug,使得輸出能正確包含 "a", "b" 和 ""。其他不涉及嚴(yán)格在 EOF 產(chǎn)生空令牌的情況,輸出行為通常是一致的。

解釋:

在 Go 1.4 及以后版本,對于輸入 "a,b,"

  • SplitFunc 找到第一個逗號,返回 "a"。
  • SplitFunc 找到第二個逗號,返回 "b"。
  • SplitFunc 找到第三個逗號,返回 "" (空字符串)。
  • 此時 data 變?yōu)?nbsp;"",Scanner 讀取發(fā)現(xiàn)已到 EOF。
  • Scanner 最后一次調(diào)用 SplitFunc,傳入 data 為 []byte("") 且 atEOF 為 true。
  • customSplit 函數(shù)根據(jù)邏輯,因為 len(data) 為 0,返回 (0, nil, nil)。
  • Scanner 接收到 (0, nil, nil) 且 atEOF 為 true,知道掃描結(jié)束。關(guān)鍵在于,第三步已經(jīng)成功返回了末尾的空令牌 ""。
責(zé)任編輯:姜華 來源: Piper蛋窩
相關(guān)推薦

2025-04-15 08:00:53

2025-04-14 00:00:04

2025-04-21 00:05:00

2025-04-21 08:00:56

2025-04-22 08:02:23

2025-04-23 08:02:40

2025-04-21 00:00:00

Go 開發(fā)Go 語言Go 1.9

2025-04-24 09:01:46

2025-04-27 08:00:35

2025-04-27 00:00:01

Go 1.16Go 1.15接口

2025-04-18 08:07:12

2025-04-17 08:00:48

2025-04-25 08:01:12

Go應(yīng)用程序部署

2025-04-28 08:00:56

2025-04-29 08:03:18

2025-04-14 00:00:00

2025-04-11 08:02:38

2025-04-10 08:03:18

Go 1rune? 類型類型推斷

2010-07-12 10:48:21

SQL Server數(shù)

2023-08-14 08:34:14

GolangHttp
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號