Go 1 版本資訊
Go 1 簡介
Go 1 版本(簡稱 Go 1)定義了一種語言以及一套核心函式庫,這些函式庫提供了穩定的基礎,可以用來建立可靠的產品、專案和文件。
推動 Go 1 的主要動力,是為其使用者提供穩定性。人們應能夠撰寫 Go 程式,並且預期它們將繼續編譯和執行而不會改變,時間尺度為多年,包括在類似 Google App Engine 等生產環境中。同樣地,人們應能夠撰寫有關 Go 的書籍,能夠說明這本書描述的是 Go 的哪個版本,並且這個版本號在很久以後仍然有意義。
在 Go 1 中編譯的程式碼應該會繼續編譯和執行在該版本的生命週期中,幾乎沒有例外,即使我們發布更新和錯誤修正程式,例如 Go 1.1、1.2 等版本。除了重大修正程式以外,對後續 Go 1 版本所做的語言和函式庫變更可能會新增功能,但不會影響現有的 Go 1 程式。Go 1 相容性文件 更詳細地說明了相容性準則。
Go 1 是 Go 語言在現今使用狀況下的表示,並非語言的全面性再思考。我們避免設計新功能,而專注於解決問題、消除不一致性,以及提升可移植性。在 Go 語言和套件中,我們已考慮、編製原型,但並未釋出一定數量的變更有一段時間,這主要是因為它們重大且不相容於以往版本。Go 1 提供了釋出它們的機會,這對長期發展有幫助,但同時也代表 Go 1 對舊程式引入了不相容性。幸運的是,go
fix
工具可以自動化多數將程式提升至 Go 1 標準所需的工作。
本文大綱說明 Go 1 中會影響程式設計師更新現有程式碼的主要變更;它參考的基準是前次發布版本 r60(標記為 r60.3)。本文也說明如何將 r60 中的程式碼更新,讓其能在 Go 1 中執行。
對語言的變更
Append
預先宣告的多變數 append
函數可以輕鬆地透過在結尾處新增元件來擴增切片。常見的應用在產生輸出時,將位元組新增至位元組切片的結尾。但是,append
未提供將字串新增至 []byte
的方法,而這是另一個常見的案例。
greeting := []byte{} greeting = append(greeting, []byte("hello ")...)
根據 copy
的類似屬性類比,Go 1 允許字串直接(以位元組方式)新增至位元組切片,減少字串和位元組切片之間的摩擦。此轉換不再必要
greeting = append(greeting, "world"...)
更新:這是新功能,因此現有程式碼不需要變更。
Close
預先宣告的 close
函數提供送受信號機制,表示不會再傳送更多值。對於在通道上進行 for
range
迴圈的實作非常重要,且在其他情況下也有幫助。部分由設計所致,部分則因為可能會出現競賽條件,因此只預期由於通道傳送資料的 goroutine 使用,而非接收資料的 goroutine 使用。不過,在 Go 1 之前,沒有編譯時期的檢查可判斷 close
是否已正確使用。
為了至少部分解決此差距,Go 1 不允許僅接收通道執行 close
。嘗試關閉此類通道會產生編譯時期錯誤。
var c chan int var csend chan<- int = c var crecv <-chan int = c close(c) // legal close(csend) // legal close(crecv) // illegal
更新:即使在 Go 1 之前,嘗試關閉僅接收通道的現有程式碼被視為錯誤,應該修正。編譯器現在會拒絕此類程式碼。
複合字面值
在 Go 1 中,陣列、切片或映射類型的複合字面值,如果為指標類型,可以省略元素初始值類型的指定。這個範例中的四個初始化動作都是合法的;最後一個在 Go 1 之前是非法的。
type Date struct { month string day int } // Struct values, fully qualified; always legal. holiday1 := []Date{ Date{"Feb", 14}, Date{"Nov", 11}, Date{"Dec", 25}, } // Struct values, type name elided; always legal. holiday2 := []Date{ {"Feb", 14}, {"Nov", 11}, {"Dec", 25}, } // Pointers, fully qualified, always legal. holiday3 := []*Date{ &Date{"Feb", 14}, &Date{"Nov", 11}, &Date{"Dec", 25}, } // Pointers, type name elided; legal in Go 1. holiday4 := []*Date{ {"Feb", 14}, {"Nov", 11}, {"Dec", 25}, }
更新:這個變更不會對既有程式碼造成影響,但套用在既有來源的 gofmt
-s
指令會在適當的地方省略顯性格元素類型,以及其他動作。
初始化期間的 Goroutine
舊的語言定義在初始化期間執行的 go
陳述式會建立 Goroutine,但直到整個程式初始化完成後才會開始執行。這在多個地方造成笨拙的狀況,並且有效限制了 init
建構式的實用性:如果其他套件可以在初始化期間使用這個函式庫,函式庫就被迫避免使用 Goroutine。這個設計是出於簡潔性和安全性的考量,但隨著我們對這門語言信心增長,看來這沒有必要。在初始化期間執行 Goroutine 並不比在正常執行期間執行更加複雜或不安全。
在 Go 1 中,可以在 init
常式和全域初始化表達式呼叫使用 Goroutine 的程式碼,而且不會造成僵局。
var PackageGlobal int func init() { c := make(chan int) go initializationFunction(c) PackageGlobal = <-c }
更新:這是新的功能,所以既有程式碼不需要變更,儘管有可能依賴在 main
之前不會啟動的 Goroutine 的程式碼會損毀。標準儲存庫中沒有這樣的程式碼。
rune 類型
語言規格允許 int
類型為 32 或 64 位元寬,但目前的實作將 int
設定為 32 位元,即使在 64 位元平台上也是如此。在 64 位元平台上,最好讓 int
為 64 位元。(索引大型切片有重要的後果。)但是,這個變更會在使用舊語言處理 Unicode 字元時浪費空間,因為 int
類型也用於儲存 Unicode 碼點:如果 int
從 32 位元增加到 64 位元,每個碼點會浪費額外的 32 位元儲存空間。
為了讓變更為 64 位元 int
可行,Go 1 推出了新的基本類型 rune
,用於代表單一的 Unicode 碼點。它是 int32
的別名,類似於 byte
是 uint8
的別名。
像 'a'
、'語'
和 '\u0345'
這樣的字元字面值現在的預設類型為 rune
,類似於 1.0
的預設類型是 float64
。因此,初始化為字元常數的變數會擁有類型 rune
,除非另有指定。
函式庫已更新為在適當時使用 rune
而非 int
。例如,函式 unicode.ToLower
和相關函式現在接受並傳回 rune
。
delta := 'δ' // delta has type rune.
var DELTA rune
DELTA = unicode.ToUpper(delta)
epsilon := unicode.ToLower(DELTA + 1)
if epsilon != 'δ'+1 {
log.Fatal("inconsistent casing for Greek")
}
更新:大部分原始碼不受此影響,因為 :=
初始值設定項目的類型推論會在無聲無息中引入新類型,並從那裡傳播出去。有些程式碼可能會出現類型錯誤,而這些錯誤可以用細微的轉換來解決。
錯誤類型
Go 1 導入新的內建類型 error
,它有下列定義
type error interface {
Error() string
}
由於這個類型的後果都在封裝程式庫中,因此在 下方 討論。
從字典刪除
在舊語言中,要從字典 m
中刪除鍵為 k
的項目,需撰寫下列陳述式,
m[k] = value, false
這個語法是個異常的特殊情況,這是唯一一個二對一指派。它需要傳遞一個值 (通常會忽略),經過評估後會被丟棄,加上幾乎都是常數 false
的布林值。它完成了任務,但這很奇怪,而且是個爭論點。
在 Go 1 中,這個語法已經消失了;取而代之的是一個新的內建函式 delete
。呼叫
delete(m, k)
會刪除由式 m[k]
擷取到的字典項目。沒有傳回值。刪除一個不存在的項目為無效操作。
更新:執行 go
fix
會將形如 m[k] = value, false
的式轉換成 delete(m, k)
,只要明確的被忽略值可以安全的從程式中丟棄,而且 false
指的是預先定義的布林常數。這個修正工具會標記語法中的其他使用,以便程式設計師檢查。
在字典中反覆運算
舊語言規格沒有定義字典的反覆運算順序,並且在實務中,它在不同的硬體平台上有所不同。這使得對字典進行反覆運算的測試很脆弱且不可移植,令人不快的是,一個測試在一個機器上可能總是通過,但在另一個機器上卻會中斷。
在 Go 1 中,使用 for
range
陳述式對字典進行反覆運算時,拜訪元素的順序被定義為不可預測,即使使用相同的字典執行同一個迴圈多次也是如此。程式碼不應假設元素以任何特定順序拜訪。
這個變更表示依賴反覆運算順序的程式碼很可能會提早中斷,並且在它成為問題前就得到修正。同樣重要的是,它允許字典實作確保更好的字典平衡,即使程式使用範圍迴圈從字典中選取元素也是如此。
m := map[string]int{"Sunday": 0, "Monday": 1}
for name, value := range m {
// This loop should not assume Sunday will be visited first.
f(name, value)
}
更新中:這是一個工具無法協助的變更。大部分現有程式碼將不受影響,但有些程式可能會中斷或出現異常行為;我們建議手動檢查所有範圍陳述式(over maps)以驗證他們不會依賴於反覆運算順序。標準存放庫中有幾個這樣的範例;它們已經修復了。請注意,依賴於反覆運算順序本來就不正確,因為它沒有指定。這個變更規定了不可預測性。
多重指定
語言規格已保證在指定時,右側表達式在任何左側表達式被指定之前都經過評估。為了保證可預測的行為,Go 1 進一步精進了規格。
如果指定陳述式的左側包含需要評估的表達式,例如函式呼叫或陣列索引運算,這些運算會先按照由左至右的規則執行,在任何變數被指定其值之前。一旦所有內容都經過評估,實際指定會按照由左至右的順序進行。
這些範例說明了此行為。
sa := []int{1, 2, 3} i := 0 i, sa[i] = 1, 2 // sets i = 1, sa[0] = 2 sb := []int{1, 2, 3} j := 0 sb[j], j = 2, 1 // sets sb[0] = 2, j = 1 sc := []int{1, 2, 3} sc[0], sc[0] = 1, 2 // sets sc[0] = 1, then sc[0] = 2 (so sc[0] = 2 at end)
更新中:這是一個工具無法協助的變更,但不太可能中斷。標準存放庫中沒有任何程式碼因這個變更而中斷,依賴於先前未指定行為的程式碼本來就不正確。
回傳值和陰影變數
一個常見的錯誤是在對與結果變數同名的變數指定(沒有參數)後使用 return
,但並非同一個變數。此情況稱為陰影:結果變數已在內部範圍宣告的另一同名變數中陰影化。
在具有命名回傳值的函式中,若回傳陳述式中的任何命名回傳值在回傳陳述式的點被陰影化,Go 1 編譯器將不允許沒有參數的回傳陳述式。(這不是規格的一部分,因為這是我們仍在探索的領域之一;此情況類似於編譯器會拒絕不以明確回傳陳述式結束的函式。)
此函式隱含地回傳一個陰影的回傳值,將會被編譯器拒絕
func Bug() (i, j, k int) { for i = 0; i < 5; i++ { for j := 0; j < 5; j++ { // Redeclares j. k += i * j if k > 100 { return // Rejected: j is shadowed here. } } } return // OK: j is not shadowed here. }
更新中:以這種方式陰影回傳值的程式碼將會被編譯器拒絕,需要手動修正。標準存放庫中出現的幾個案例大多是錯誤。
複製具有未匯出的欄位的結構
舊語言不允許套件複製包含屬於不同套件的未匯出欄位的結構值。不過,函式接收者有一個必要的例外;另外,copy
和 append
的實作從未遵守此限制。
Go 1 將允許套件複製包含來自其他套件的未匯出欄位的結構值。除了解決不一致性之外,這個變更允許一種新的 API:套件可以在不訴諸指標或介面的情況下回傳一個不透明值。time.Time
和 reflect.Value
的新實作就是利用這個新特性的類型範例。
例如,封包 p
包含定義,
type Struct struct {
Public int
secret int
}
func NewStruct(a int) Struct { // Note: not a pointer.
return Struct{a, f(a)}
}
func (s Struct) String() string {
return fmt.Sprintf("{%d (secret %d)}", s.Public, s.secret)
}
匯入 p
的封包可以隨意指定及複製類型為 p.Struct
的值。在看不见的地方,未導出的欄位會像導出的欄位一樣被指定和複製,但用戶代碼永遠不會意識到它們。程式碼
import "p"
myStruct := p.NewStruct(23)
copyOfMyStruct := myStruct
fmt.Println(myStruct, copyOfMyStruct)
將顯示結構的秘密欄位已複製到新值。
更新:這是新功能,因此現有程式碼不需要變更。
相等
在 Go 1 之前,語言並未定義結構和陣列值的相等性。這表示結構和陣列不能用作對應值一樣。另一方面,Go 確實定義了函數和對應值的相等性。函數相等性在閉包中是有問題的(什麼時候兩個閉包相等?)而對應值相等性是比較指標,而不是對應值的內容,這通常不是使用者想要的。
Go 1 解决了這些問題。首先,結構和陣列可以比較相等或不相等(==
和 !=
),因此可以用作對應值金鑰,前提是它們由也定義了相等性的元素組成,使用逐元素比較。
type Day struct { long string short string } Christmas := Day{"Christmas", "XMas"} Thanksgiving := Day{"Thanksgiving", "Turkey"} holiday := map[Day]bool{ Christmas: true, Thanksgiving: true, } fmt.Printf("Christmas is a holiday: %t\n", holiday[Christmas])
其次,Go 1 移除了函數值的相等性定義,除非與 nil
進行比較。最後,對應值相等性也消失了,也僅限於與 nil
進行比較。
請注意,相等性對於區塊仍然未定義,對區塊進行計算通常不可行。另外請注意,順序比較運算子 (< <= >
>=
) 對於結構和陣列仍然未定義。
更新:結構和陣列相等性是一項新功能,因此現有代碼不需要變更。依賴於函數或對應值相等性的現有代碼將被編譯器拒絕,需要透過手動修復。受影響的程式很少,但修復可能需要重新設計。
封包階層
Go 1 解决了舊標準函式库中的許多缺陷,並整理了許多封包,讓它們在內部更一致且可攜帶。
本節說明 Go 1 中封包的重新排列方式。有些封包已移至他處,有些封包已重新命名,有些封包已刪除。後面的部分描述了新的封包。
封包階層
Go 1 有重新排列的套件階層,將相關項目分組到子目錄中。例如,utf8
和 utf16
現在位於 unicode
的子目錄中。此外,某些套件 已移至 code.google.com/p/go
的子儲存庫中,而 另一些 已直接刪除。
舊路徑 | 新路徑 |
---|---|
asn1 | encoding/asn1 |
csv | encoding/csv |
gob | encoding/gob |
json | encoding/json |
xml | encoding/xml |
exp/template/html | html/template |
big | math/big |
cmath | math/cmplx |
rand | math/rand |
http | net/http |
http/cgi | net/http/cgi |
http/fcgi | net/http/fcgi |
http/httptest | net/http/httptest |
http/pprof | net/http/pprof |
net/mail | |
rpc | net/rpc |
rpc/jsonrpc | net/rpc/jsonrpc |
smtp | net/smtp |
url | net/url |
exec | os/exec |
scanner | text/scanner |
tabwriter | text/tabwriter |
template | text/template |
template/parse | text/template/parse |
utf8 | unicode/utf8 |
utf16 | unicode/utf16 |
請注意,舊的 cmath
和 exp/template/html
套件的套件名稱已變更為 cmplx
和 template
。
更新:執行 go
fix
將更新所有匯入和重新命名的套件,這些套件仍保留在標準儲存庫內。匯入標準儲存庫中不再存在的套件的程式碼需要手動編輯。
exp 套件樹
由於未標準化,exp
目錄下的套件將不會出現在標準 Go 1 發行版本中,儘管它們將以原始碼的形式出現在 儲存庫 中供開發人員使用。
在 Go 1 的發行版中,有幾個套件已移至 exp
之下
ebnf
html
†go/types
(†EscapeString
和 UnescapeString
類型仍保留在套件 html
中。)
所有這些套件都在相同的名稱下提供,前綴為 exp/
:exp/ebnf
等。
此外,utf8.String
類型已移至其自己的套件 exp/utf8string
。
最後,gotype
命令現在位於 exp/gotype
中,而 ebnflint
現在位於 exp/ebnflint
中。如果已安裝,它們現在位於 $GOROOT/bin/tool
中。
更新:使用 exp
中套件的程式碼需要手動更新,否則從提供 exp
的安裝進行編譯。go
fix
工具或編譯器將抱怨此類使用情況。
old 套件樹
由於這些套件已過時,儘管標準 Go 1 發行版中的 old
目錄中沒有這些套件,但它們仍以原始碼形式提供給想要使用這些套件的開發人員。
這些套件在新位置中
old/netchan
更新:需要手動更新使用目前位於 old
中的套件的程式碼,或者從提供 old
的安裝中編譯。go
fix
工具會對此類使用提出警告。
已刪除的套件
Go 1 直接刪除下列幾個套件
container/vector
exp/datafmt
go/typechecker
old/regexp
old/template
try
以及 gotry
命令。
更新:應將使用 container/vector
的程式碼更新為直接使用陣列切片。請參閱Go 語言社群 Wiki,了解一些建議。使用其他套件(幾乎沒有)的程式碼需要重新思考。
移至子儲存庫的套件
Go 1 將一些套件移至其他儲存庫,通常是 主要 Go 儲存庫 的子儲存庫。此表格列出舊的和新的匯入路徑
舊有 | 新的 |
---|---|
crypto/bcrypt | code.google.com/p/go.crypto/bcrypt |
crypto/blowfish | code.google.com/p/go.crypto/blowfish |
crypto/cast5 | code.google.com/p/go.crypto/cast5 |
crypto/md4 | code.google.com/p/go.crypto/md4 |
crypto/ocsp | code.google.com/p/go.crypto/ocsp |
crypto/openpgp | code.google.com/p/go.crypto/openpgp |
crypto/openpgp/armor | code.google.com/p/go.crypto/openpgp/armor |
crypto/openpgp/elgamal | code.google.com/p/go.crypto/openpgp/elgamal |
crypto/openpgp/errors | code.google.com/p/go.crypto/openpgp/errors |
crypto/openpgp/packet | code.google.com/p/go.crypto/openpgp/packet |
crypto/openpgp/s2k | code.google.com/p/go.crypto/openpgp/s2k |
crypto/ripemd160 | code.google.com/p/go.crypto/ripemd160 |
crypto/twofish | code.google.com/p/go.crypto/twofish |
crypto/xtea | code.google.com/p/go.crypto/xtea |
exp/ssh | code.google.com/p/go.crypto/ssh |
image/bmp | code.google.com/p/go.image/bmp |
image/tiff | code.google.com/p/go.image/tiff |
net/dict | code.google.com/p/go.net/dict |
net/websocket | code.google.com/p/go.net/websocket |
exp/spdy | code.google.com/p/go.net/spdy |
encoding/git85 | code.google.com/p/go.codereview/git85 |
patch | code.google.com/p/go.codereview/patch |
exp/wingui | code.google.com/p/gowingui |
更新:執行 go
fix
會使用新的匯入路徑更新這些套件的匯入。依賴這些套件的安裝需要使用 go get
命令安裝這些套件。
函式庫的主要變更
此單元說明核心函式庫的重大變更,也就是會影響最多程式的那一類變更。
錯誤類型和 errors 套件
將 os.Error
放入 os
套件中大部分是出於歷史因素:錯誤最早在實作 os
套件時產生,當時看來與系統有關。從那時起,就很明顯地看出,錯誤比作業系統更基本。例如,將 Error
用在 os
所依賴的套件中會很好,例如 syscall
。另外,將 Error
放在 os
中會引入許多對 os
的依賴關係,否則並不存在這些關係。
Go 1 透過引入內建 error
介面類型和一個單獨的 errors
套件(類似於 bytes
和 strings
)來解決這些問題,其中包含工具函式。它使用 errors.New
來取代 os.NewError
,讓錯誤在環境中更為核心。
因此,廣泛使用的 String
方法不會造成意外滿足 error
介面,error
介面會改用 Error
作為該方法的名稱
type error interface {
Error() string
}
fmt
函式庫會自動呼叫 Error
,就像它已經對 String
做的那樣,用於輕鬆列印錯誤的值。
type SyntaxError struct { File string Line int Message string } func (se *SyntaxError) Error() string { return fmt.Sprintf("%s:%d: %s", se.File, se.Line, se.Message) }
所有標準套件都已更新成使用新的介面;舊的 os.Error
不復存在。
一個新的套件 errors
包含這個函式
func New(text string) error
用於將字串轉換成錯誤。它取代舊的 os.NewError
。
var ErrSyntax = errors.New("syntax error")
更新:執行 go
fix
將會更新幾乎所有受變更影響的程式碼。使用 String
方法來定義錯誤類型的程式碼,需要手動更新,將方法重新命名為 Error
。
系統呼叫錯誤
舊版的 syscall
套件早於 os.Error
(還有其他所有東西),會傳回 int
值作為錯誤。反過來,os
套件轉發許多這些錯誤,例如 EINVAL
,但是每個平台都使用不同的錯誤集。這種行為令人不愉快且無法移植。
在 Go 1 中,syscall
套件會針對系統呼叫錯誤傳回 error
。在 Unix 上,實作是由滿足 error
的 syscall.Errno
類型所完成,並取代舊的 os.Errno
。
影響 os.EINVAL
和相關訊息的變更已在 其他地方 描述。
更新:執行 go
fix
將會更新幾乎所有受變更影響的程式碼。無論如何,大部分程式碼應使用 os
套件,而非 syscall
,因此不會受到影響。
時間
在程式語言中永遠難以完善地支援時間。舊版 Go time
套件具有 int64
單位,沒有真正的類型安全性,也無法區分絕對時間和時段。
因此,Go 1 程式庫中最廣泛的變更之一便是徹底重新設計了 time
套件。與使用 int64
表示整數奈秒數,以及單獨使用 *time.Time
類型來處理小時和年等人類單位的方式不同,現在有兩個基本類型:time.Time
(一個值,因此 *
已移除),表示時間點;以及 time.Duration
,表示一個區間。兩者都具備奈秒解析度。Time
可以表示任何時間,無論是發生於久遠的過去或遙遠的未來,而 Duration
則只能跨越正負約 290 年。這些類型中有方法,以及許多有用的預設常數持續時間(例如 time.Second
)。
在新的方法中,包含像 Time.Add
之類的方法,可將 Duration
加到 Time
中,以及 Time.Sub
之類的方法,可從兩個 Times
中減掉一個 Duration
。
最重要的語意變更在於 Unix 紀元(1970 年 1 月 1 日)現在僅與那些提到 Unix 的函式及方法相關:time.Unix
以及 Time
類型的 Unix
和 UnixNano
方法。特別是,time.Now
傳回 time.Time
值,而不是如舊 API 中所傳回的那樣為自 Unix 紀元起算計以奈秒為單位的整數。
// sleepUntil sleeps until the specified time. It returns immediately if it's too late. func sleepUntil(wakeup time.Time) { now := time.Now() // A Time. if !wakeup.After(now) { return } delta := wakeup.Sub(now) // A Duration. fmt.Printf("Sleeping for %.3fs\n", delta.Seconds()) time.Sleep(delta) }
新的類型、方法和常數已傳播到所有使用時間的標準套件,例如 os
及其檔案時間戳記表示方式。
更新:go
fix
工具會將許多使用舊 time
套件的程式碼更新為使用新的類型及方法,儘管它不會取代表示每秒奈秒數的 1e9
等值。此外,由於一些產生的值中類型已變更,因此一些由修正工具改寫的表達式可能需要進一步人工編輯;在這種情況下,改寫將包含適用於舊功能的正確函式或方法,但可能類型錯誤或需要進一步分析。
程式庫微小的變更
本節描述較小的變更,例如對不常使用的套件所做的變更,或除了需要執行 go
fix
之外,僅影響少數程式碼的變更。此類別包含 Go 1 中新增的套件。它們會集體改善可攜性、規範化行為,並使介面更現代且更類似 Go。
archive/zip 套件
在 Go 1 中,*zip.Writer
不再擁有 Write
方法。它的存在是一個錯誤。
更新:少部分受影響的程式碼將會被編譯器偵測到,而且必須手動更新。
bufio 套件
在 Go 1 中,bufio.NewReaderSize
和 bufio.NewWriterSize
函式不再會為無效的大小傳回錯誤。如果設定的大小過小或無效,它會進行調整。
更新:使用 go
fix
會更新將錯誤指定給 _ 的呼叫。編譯器會攔截未修正的呼叫,且它們必須手動更新。
compress/flate、compress/gzip 與 compress/zlib 套件
在 Go 1 中,compress/flate
、compress/gzip
與 compress/zlib
中的 NewWriterXxx
函式如果採用壓縮級別,則全部都會傳回 (*Writer, error)
;否則會傳回 *Writer
。gzip
套件的 Compressor
與 Decompressor
類型已更名為 Writer
與 Reader
。flate
套件的 WrongValueError
類型已被移除。
更新:執行 go
fix
會更新舊名稱與將錯誤指定給 _ 的呼叫。編譯器會攔截未修正的呼叫,且它們必須手動更新。
crypto/aes 與 crypto/des 套件
在 Go 1 中,Reset
方法已被移除。Go 不保證不複製記憶體,因此這個方法具有誤導性。
具體到密碼的類型 *aes.Cipher
、*des.Cipher
與 *des.TripleDESCipher
已基於 cipher.Block
而遭移除。
更新:移除對 Reset 的呼叫。將特定密碼類型的用處替換為 cipher.Block。
crypto/elliptic 套件
在 Go 1 中,elliptic.Curve
已成為介面,以允許其他實作。曲線參數已移至 elliptic.CurveParams
結構。
更新:*elliptic.Curve
的現有使用者需要變更為單純的 elliptic.Curve
。Marshal
、Unmarshal
與 GenerateKey
的呼叫現在為 crypto/elliptic
中的函式,在這些函式中 elliptic.Curve
為其第一個引數。
crypto/hmac 套件
在 Go 1 中,具有特定雜湊的函式(例如 hmac.NewMD5
)已從 crypto/hmac
中移除。hmac.New
取而代之,它採用傳回 hash.Hash
的函式,例如 md5.New
。
更新:執行 go
fix
會執行所需的變更。
crypto/x509 套件
在 Go 1 中,crypto/x509
中的 CreateCertificate
函式與 CreateCRL
方法已更動,它們在以前採取 *rsa.PublicKey
或 *rsa.PrivateKey
的地方,改採 interface{}
。這將允許在未來實作出其他公開金鑰演算法。
更新:無需變更。
encoding/binary 套件
在 Go 1 中,binary.TotalSize
函式已由 Size
取代,後者採用 interface{}
參數,而非 reflect.Value
。
更新:少部分受影響的程式碼將會被編譯器偵測到,而且必須手動更新。
encoding/xml 套件
在 Go 1 中,xml
套件的設計已接近其他編組解編器套件,例如 encoding/gob
。
舊有的 Parser
類型已重新命名為 Decoder
並具有新的 Decode
方法。此外,還新增了 Encoder
類型。
函式 Marshal
和 Unmarshal
現在採用 []byte
值。如要與串流搭配使用,請使用新的 Encoder
和 Decoder
類型。
在編組解編器數值時,欄位標籤中受支持旗標的格式已變更,以接近 json
套件 (`xml:"name,flag"`
)。現在,欄位標籤、欄位名稱以及 XML 屬性和元素名稱之間的比對會區分大小寫。如果存在 XMLName
欄位標籤,則其也必須與即將編組解編的 XML 元素名稱相符。
更新: 執行 go
fix
會更新套件的大多數使用方式,唯獨 Unmarshal
的部分呼叫除外。欄位標籤必須特別注意,因為修正工具不會更新它們;若未手動修正,它們在某些情況下會靜默異常。例如,舊有的 "attr"
現在寫成 ",attr"
,而純粹的 "attr"
仍然有效,但意義不同。
expvar 套件
在 Go 1 中,已移除 RemoveAll
函式。Iter
函式與 *Map
的 Iter 方法已分別由 Do
和 (*Map).Do
取代。
更新: 大多數使用 expvar
的程式碼不需要更動。某些罕見使用了 Iter
的程式碼可以更新為傳遞封閉元件至 Do
以達成相同的成效。
flag 套件
在 Go 1 中,介面 flag.Value
已略有變動。現在,Set
方法會傳回 error
而非 bool
,以表示成功或失敗。
此外,新增了一種類型的 Duration
旗標,以支援指定時間區間的參數值。此類旗標的值必須加上單位,正如同 time.Duration
格式化方式:10s
、1h30m
等。
var timeout = flag.Duration("timeout", 30*time.Second, "how long to wait for completion")
更新: 實作自家旗標的程式會需要進行輕微的手動修正,以更新其 Set
方法。Duration
旗標是新功能,不會影響現有程式碼。
go/* 套件
go
下的幾個套件已稍微修正了 API。
針對套件 go/scanner
、go/parser
、go/printer
和 go/doc
中的組態模式旗標,已引入具體的 Mode
類型。
已從 go/scanner
套件中移除 AllowIllegalChars
和 InsertSemis
模式。這些模式主要用於掃描 Go 原始檔以外的文字。建議改用 text/scanner
套件處理此類目的。
現在提供給掃描器 Init
方法的 ErrorHandler
只是一個函式,不再是介面。已經移除 ErrorVector
類型,轉而採用 (現有的) ErrorList
類型,並已移植 ErrorVector
方法。現在,不用在掃描器的用戶端內嵌 ErrorVector
,而應該維護一個 ErrorList
。
由 go/parser
套件提供的剖析函數集合已減少為主要剖析函數 ParseFile
,以及幾個便利函數 ParseDir
和 ParseExpr
。
go/printer
套件支援額外的組態模式 SourcePos
;如果設為這個模式,印表機將發出 //line
註解,使產生的輸出包含原始原始碼位置資訊。新類型 CommentedNode
可用來提供與任意 ast.Node
相關的註解 (到目前為止,只有 ast.File
會傳送註解資訊)。
go/doc
套件的類型名稱已透過移除 Doc
字尾變得更精簡:PackageDoc
現在變成了 Package
,ValueDoc
變成了 Value
等。此外,所有類型現在都持續有一個 Name
欄位 (或是 Names
,例如 Value
類型),而 Type.Factories
則已變成 Type.Funcs
。現在可透過 doc.NewPackageDoc(pkg, importpath)
來建立套件的文件,
doc.New(pkg, importpath, mode)
其中新的 mode
參數會指定操作模式:若設定為 AllDecls
,會考量所有宣告 (而不只是外傳宣告)。已移除 NewFileDoc
函數,而 CommentText
函數已變成 ast.CommentGroup
的 Text
方法。
在套件 go/token
中,token.FileSet
方法 Files
(最初會傳回一個 *token.File
s 通道) 已改為迭代器 Iterate
,並接受函式引數。
在 go/build
套件中,API 已幾近完全替換。該套件仍會計算 Go 套件資訊,但不會執行編譯:Cmd
和 Script
型別已經不見了。(改用新的 go
命令進行編譯。)DirInfo
型別現在的名稱為 Package
。FindTree
和 ScanDir
已被 Import
和 ImportDir
取代。
更新:在 go
中使用套件的程式碼必須手動更新;編譯器會拒絕使用不正確的方式。與 go/doc
任何型別搭配使用的範本可能需要手動修正;重新命名的欄位會導致執行階段錯誤。
雜湊套件
在 Go 1 中,hash.Hash
的定義包含一個新的方法,BlockSize
。這個新方法主要用於加密程式庫。
hash.Hash
介面的 Sum
方法現在採用 []byte
參數,雜湊值將附加到該參數。可以透過新增 nil
參數至呼叫來重新建立之前的行為。
更新:hash.Hash
的既有實作需要新增一個 BlockSize
方法。處理輸入資料每次一個位元的雜湊可以實作 BlockSize
來傳回 1。執行 go
fix
會更新對 hash.Hash
各種實作的 Sum
方法的呼叫。
更新:由於該套件的功能是新的,因此不需要更新。
http 套件
在 Go 1 中,http
套件經過重構,將一些工具函式放入 httputil
子目錄。HTTP 客戶端鮮少需要這些部分。受到影響的項目包括
- ClientConn
- DumpRequest
- DumpRequestOut
- DumpResponse
- NewChunkedReader
- NewChunkedWriter
- NewClientConn
- NewProxyClientConn
- NewServerConn
- NewSingleHostReverseProxy
- ReverseProxy
- ServerConn
Request.RawURL
欄位已移除;它是一種歷史人為因素。
Handle
和 HandleFunc
函式,以及 ServeMux
的同名方法,現在在嘗試註冊同一個模式兩次時,會發生恐慌。
更新:執行 go
fix
會更新少數受到影響的程式,RawURL
用法除外,必須手動修正。
image 套件
image
套件進行了不少微小的變更、重新配置和重新命名。
大多數色彩處理程式碼都已移至其專屬套件 image/color
中。對於已移走的元素,對稱性會隨之出現;例如,image.RGBA
中的每個像素都是 color.RGBA
。
舊的 image/ycbcr
套件已透過一些更名動作,合併至 image
和 image/color
套件中。
舊的 image.ColorImage
類型仍存在於 image
套件中,但已更名為 image.Uniform
,同時 image.Tiled
已移除。
下表列出更名記錄。
舊有 | 新的 |
---|---|
image.Color | color.Color |
image.ColorModel | color.Model |
image.ColorModelFunc | color.ModelFunc |
image.PalettedColorModel | color.Palette |
image.RGBAColor | color.RGBA |
image.RGBA64Color | color.RGBA64 |
image.NRGBAColor | color.NRGBA |
image.NRGBA64Color | color.NRGBA64 |
image.AlphaColor | color.Alpha |
image.Alpha16Color | color.Alpha16 |
image.GrayColor | color.Gray |
image.Gray16Color | color.Gray16 |
image.RGBAColorModel | color.RGBAModel |
image.RGBA64ColorModel | color.RGBA64Model |
image.NRGBAColorModel | color.NRGBAModel |
image.NRGBA64ColorModel | color.NRGBA64Model |
image.AlphaColorModel | color.AlphaModel |
image.Alpha16ColorModel | color.Alpha16Model |
image.GrayColorModel | color.GrayModel |
image.Gray16ColorModel | color.Gray16Model |
ycbcr.RGBToYCbCr | color.RGBToYCbCr |
ycbcr.YCbCrToRGB | color.YCbCrToRGB |
ycbcr.YCbCrColorModel | color.YCbCrModel |
ycbcr.YCbCrColor | color.YCbCr |
ycbcr.YCbCr | image.YCbCr |
ycbcr.SubsampleRatio444 | image.YCbCrSubsampleRatio444 |
ycbcr.SubsampleRatio422 | image.YCbCrSubsampleRatio422 |
ycbcr.SubsampleRatio420 | image.YCbCrSubsampleRatio420 |
image.ColorImage | image.Uniform |
image 套件的 New
函式 (NewRGBA
、NewRGBA64
等) 會將 image.Rectangle
視為引數,而非四個整數。
最後,有新的預先定義的 color.Color
變數 color.Black
、color.White
、color.Opaque
和 color.Transparent
。
更新:執行 go
fix
將更新幾乎所有受變更影響的程式碼。
log/syslog 套件
在 Go 1 中,syslog.NewLogger
函式會傳回錯誤以及 log.Logger
。
更新:少部分受影響的程式碼將會被編譯器偵測到,而且必須手動更新。
mime 套件
在 Go 1 中,mime
套件的 FormatMediaType
函式已簡化,以與 ParseMediaType
保持一致。它現在採用 "text/html"
,而非 "text"
和 "html"
。
更新:少部分受影響的程式碼將會被編譯器偵測到,而且必須手動更新。
net 套件
在 Go 1 中,各種 SetTimeout
、SetReadTimeout
和 SetWriteTimeout
方法已分別改為 SetDeadline
、SetReadDeadline
和 SetWriteDeadline
。新方法並非接收以奈秒為單位的逾時值並套用至連線上的任何活動,而是設定絕對逾時 (為 time.Time
值),在逾時後,讀取和寫入將逾時並不再封鎖。
還新增了 net.DialTimeout
函式,以簡化計時逾時撥打網路地址,以及 net.ListenMulticastUDP
函式,以允許透過多個偵聽器並行偵聽組播 UDP。net.ListenMulticastUDP
函式取代了舊的 JoinGroup
和 LeaveGroup
方法。
更新:使用舊方法的程式碼將無法編譯且必須手動更新。語意變更使修復工具難以自動更新。
os 套件
Time
函式已移除;呼叫者應使用 time
套件中的 Time
類型。
Exec
函式已移除;呼叫者應使用 syscall
套件中的 Exec
(如果可用)。
ShellExpand
函式已重新命名為 ExpandEnv
。
NewFile
函式現在接收 uintptr
fd,而非 int
。檔案上的 Fd
方法現在也傳回 uintptr
。
由於值集會隨著底層作業系統而異,因此 os
套件中不再有 EINVAL
等錯誤常數。有新的可攜式函式,例如 IsPermission
,用於測試常見的錯誤屬性,另有少數新錯誤值具有更類 Go 的名稱,例如 ErrPermission
和 ErrNotExist
。
Getenverror
函式已移除。若要區分不存在的環境變數和空字串,請使用 os.Environ
或 syscall.Getenv
。
Process.Wait
方法已移除其選項引數,且相關常數也已從套件中移除。此外,Wait
函式已移除;只有 Process
類型的 Wait
方法才存在。
Process.Wait
返回的 Waitmsg
型態已替換為功能更強大的 ProcessState
型態,且內含存取方法以取得程序資訊。由於對 Wait
的變動,ProcessState
值永遠會描述一個已結束的程序。由於為達成可移植性,依其他方式簡化了介面,但 ProcessState.Sys
及 ProcessState.SysUsage
方法所回傳的值,可以型別斷言為底層特定於系統的資料結構,例如 Unix 中的 syscall.WaitStatus
及 syscall.Rusage
。
更新:執行 go
fix
會捨棄 Process.Wait
的零個引數。所有其他變動會被編譯器偵測到,且必須手動更新。
os.FileInfo 型態
Go 1 重新定義 os.FileInfo
型態,將其從結構變更為介面
type FileInfo interface {
Name() string // base name of the file
Size() int64 // length in bytes
Mode() FileMode // file mode bits
ModTime() time.Time // modification time
IsDir() bool // abbreviation for Mode().IsDir()
Sys() interface{} // underlying data source (can return nil)
}
檔案模式資訊已移至名為 os.FileMode
的子型態,此為純整數型態,內含 IsDir
、Perm
、及 String
方法。
檔案模式和屬性 (在 Unix 上為 i-node) 的特定於系統的詳細資料已從 FileInfo
中移除。取而代之的是,每個作業系統的 os
套件提供 FileInfo
介面的實作,此介面內含方法 Sys
,可以回傳檔案中繼資料的特定於系統的表示。例如,若要找出 Unix 系統上檔案的 i-node,請依下列方式解開 FileInfo
fi, err := os.Stat("hello.go")
if err != nil {
log.Fatal(err)
}
// Check that it's a Unix file.
unixStat, ok := fi.Sys().(*syscall.Stat_t)
if !ok {
log.Fatal("hello.go: not a Unix file")
}
fmt.Printf("file i-number: %d\n", unixStat.Ino)
假設 (這是不明智的) "hello.go"
是 Unix 檔案,則 i-node 表達式可以簡寫成
fi.Sys().(*syscall.Stat_t).Ino
絕大多數使用 FileInfo
的狀況只需要標準介面的方法。
os
套件不再包含 POSIX 錯誤的包裝函數,例如 ENOENT
。對於需要驗證特定錯誤條件的少數程式,現在有布林函數 IsExist
、IsNotExist
和 IsPermission
。
f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) if os.IsExist(err) { log.Printf("%s already exists", name) }
更新:執行 go
fix
會更新使用舊版等效於目前的 os.FileInfo
和 os.FileMode
API 的程式碼。需要特定於系統的檔案詳細資料的程式碼需要手動更新。使用舊版 os
套件中的 POSIX 錯誤值的程式碼會無法編譯,且也需要手動更新。
os/signal 套件
Go 1 中的 os/signal
套件取代了 Incoming
函數,該函數回傳接收所有輸入訊號的通道,取而代之的是選擇性的 Notify
函數,此函數要求在現有通道上傳遞特定訊號。
更新:程式碼必須手動更新。逐字翻譯是
c := signal.Incoming()
而是
c := make(chan os.Signal, 1)
signal.Notify(c) // ask for all signals
但大多數程式碼都應該列出它想要處理的特定訊號
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT)
path/filepath 套件
在 Go 1 中,path/filepath
套件中的 Walk
函數已變更為採用 WalkFunc
型別的函數值,而不是 Visitor
介面值。WalkFunc
會將檔案與目錄的處理統一。
type WalkFunc func(path string, info os.FileInfo, err error) error
WalkFunc
函數將會呼叫,即使無法開啟檔案或目錄;在這種情況下,錯誤引數會示述失敗。如果目錄的內容要略過,函數應傳回值 filepath.SkipDir
markFn := func(path string, info os.FileInfo, err error) error {
if path == "pictures" { // Will skip walking of directory pictures and its contents.
return filepath.SkipDir
}
if err != nil {
return err
}
log.Println(path)
return nil
}
err := filepath.Walk(".", markFn)
if err != nil {
log.Fatal(err)
}
更新:變更簡化大部分程式碼,但有微妙的結果,因此受影響的程式需要手動更新。編譯器會偵測使用舊介面的程式碼。
regexp 套件
regexp
套件已經改寫。其介面相同,但其支援的正規表示式的規格已從舊的「egrep」形式變更為 RE2 的形式。
更新:使用套件的程式碼應手動檢查其正規表示式。
runtime 套件
在 Go 1 中,套件 runtime
外部呼叫的絕大部分 API 已移除,而改由其他套件所提供的功能取代。使用 runtime.Type
介面或其特定具體型別實作的程式碼現在應使用套件 reflect
。使用 runtime.Semacquire
或 runtime.Semrelease
的程式碼應使用管道或套件 sync
中的抽象。runtime.Alloc
、runtime.Free
和 runtime.Lookup
函數為針對偵錯記憶體配置器而建立的非安全 API,沒有任何替換。
以前,runtime.MemStats
是儲存關於記憶體配置資訊的全球變數,呼叫 runtime.UpdateMemStats
來確保其為最新狀態。在 Go 1 中,runtime.MemStats
為結構型別,程式碼應使用 runtime.ReadMemStats
來取得目前的狀態。
此套件新增一個函數, runtime.NumCPU
,此函數會傳回作業系統核心報告的可用於平行執行的 CPU 數目。其值可以通知 GOMAXPROCS
的設定。runtime.Cgocalls
和 runtime.Goroutines
函數已重新命名為 runtime.NumCgoCall
和 runtime.NumGoroutine
。
更新:執行 go
fix
將會更新函數重新命名的程式碼。其他程式碼則需要手動更新。
strconv 套件
在 Go 1 中,strconv
套件已大幅重新設計,使其更具有 Go 樣式,而減少 C 樣式,儘管 Atoi
仍存在(類似於 int(ParseInt(x, 10, 0))
),就像 Itoa(x)
(FormatInt(int64(x), 10)
)一樣。有些函式也會新增變體,這些變體會附加到位元組區段而不是傳回字串,以便控制配給。
此表格總結了重新命名的部分,完整的詳細內容請參閱 套件文件。
舊呼叫 | 新呼叫 |
---|---|
Atob(x) | ParseBool(x) |
Atof32(x) | ParseFloat(x, 32)§ |
Atof64(x) | ParseFloat(x, 64) |
AtofN(x, n) | ParseFloat(x, n) |
Atoi(x) | Atoi(x) |
Atoi(x) | ParseInt(x, 10, 0)§ |
Atoi64(x) | ParseInt(x, 10, 64) |
Atoui(x) | ParseUint(x, 10, 0)§ |
Atoui64(x) | ParseUint(x, 10, 64) |
Btoi64(x, b) | ParseInt(x, b, 64) |
Btoui64(x, b) | ParseUint(x, b, 64) |
Btoa(x) | FormatBool(x) |
Ftoa32(x, f, p) | FormatFloat(float64(x), f, p, 32) |
Ftoa64(x, f, p) | FormatFloat(x, f, p, 64) |
FtoaN(x, f, p, n) | FormatFloat(x, f, p, n) |
Itoa(x) | Itoa(x) |
Itoa(x) | FormatInt(int64(x), 10) |
Itoa64(x) | FormatInt(x, 10) |
Itob(x, b) | FormatInt(int64(x), b) |
Itob64(x, b) | FormatInt(x, b) |
Uitoa(x) | FormatUint(uint64(x), 10) |
Uitoa64(x) | FormatUint(x, 10) |
Uitob(x, b) | FormatUint(uint64(x), b) |
Uitob64(x, b) | FormatUint(x, b) |
更新:執行 go
fix
將更新幾乎所有受變更影響的程式碼。
§ Atoi
會持續存在,但 Atoui
及 Atof32
不會,因此這些可能需要手動加入的強制轉換;go
fix
工具會警告此事。
範本套件
template
和 exp/template/html
套件已移至 text/template
及 html/template
。更重要的是,這些套件的介面已簡化。「範本集」的概念已經消失,且這些套件的函式和方法也因此有所變更,通常是透過移除來變更。
Template
物件不會再使用集,而是可能會包含多個具名稱的範本定義,實際上是在建立名稱空間以供範本呼叫。範本可以呼叫與其關聯的任何其他範本,但只能呼叫與其關聯的那些範本。關聯範本最簡單的方法就是將它們一同剖析,而套件的新架構也讓這個步驟變得更簡單。
更新中:這些匯入會由修正工具更新。單一範本用量將大致不受影響。組合使用多項範本的程式碼則需要手動更新。text/template
文件中的 範例 可提供指導。
testing 套件
testing 套件具有型別 B
,傳遞為基準測試函數的引數。在 Go 1 中,B
具有一些新方法,類似於 T
,可啟用記錄和失敗報告。
func BenchmarkSprintf(b *testing.B) {
// Verify correctness before running benchmark.
b.StopTimer()
got := fmt.Sprintf("%x", 23)
const expect = "17"
if expect != got {
b.Fatalf("expected %q; got %q", expect, got)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
fmt.Sprintf("%x", 23)
}
}
更新中:現有的程式碼不受影響,儘管使用 println
或 panic
的基準測試應更新為使用新方法。
testing/script 套件
testing/script 套件已被刪除。它是一個糟粕。
更新中:沒有程式碼會受到影響。
unsafe 套件
在 Go 1 中,函數 unsafe.Typeof
、unsafe.Reflect
、unsafe.Unreflect
、unsafe.New
和 unsafe.NewArray
已被移除;它們重複了套件 reflect
所提供的更安全的執行功能。
更新中:使用這些函數的程式碼必須改寫為使用套件 reflect
。對 encoding/gob 和 通訊協定緩衝程式庫 的變更可以作為範例提供說明。
url 套件
在 Go 1 中,url.URL
型別中的幾個欄位已被移除或取代。
String
現在可預測地重新建構一個編碼的 URL 字串,其中使用所有 URL
的欄位。產生的字串中也不再對密碼進行跳脫。
Raw
欄位已被移除。在多數情況下,String
方法可以用在其位置上。
舊的 RawUserinfo
欄位已被 User
欄位取代,其型別為 *net.Userinfo
。此類型的值可以使用新的 net.User
和 net.UserPassword
函數建立。EscapeUserinfo
和 UnescapeUserinfo
函數也已移除。
RawAuthority
欄位已被移除。相同的資訊可在 Host
和 User
欄位中取得。
RawPath
欄位和 EncodedPath
方法已移除。根 URL 中的路徑資訊(在 schema 之後跟著斜線)現在只能在 Path
欄位中以已解碼的形式取得。偶爾情況下,為取得已在解碼過程中遺失的資訊而需要使用編碼資料。這些情況必須透過存取用來建構 URL 的資料來處理。
處理非根目錄路徑的 URL,例如「mailto:dev@golang.org?subject=Hi
」時的方式也不太一樣。已移除 OpaquePath
布林欄位,並額外新增一個名為 Opaque
的字串欄位,以保存此類 URL 編碼的路徑。在 Go 1 中,引用的 URL 會剖析為
URL{
Scheme: "mailto",
Opaque: "dev@golang.org",
RawQuery: "subject=Hi",
}
已新增一個新的
方法至 RequestURI
URL
。
已將 ParseWithReference
函式改名為 ParseWithFragment
。
更新:使用舊欄位程式碼將無法編譯,且必須手動更新。此類語意變更讓修正工具難以自動更新。
go 命令
Go 1 新增了 go 命令,這個工具可供查詢、編譯和安裝 Go 套件和命令。go
命令會捨棄 makefile,改用 Go 原始碼來尋找相依模組,並判斷編譯條件。大多數現有的 Go 程式不再需要 makefile 即可編譯。
參閱 如何撰寫 Go 程式碼,以了解 go
命令的入門介紹,並參閱 go 命令文件 以進一步了解所有詳細資訊。
更新:仰賴舊版 Go 專案 makefile 建置架構 (例如 Make.pkg
、Make.cmd
等) 的專案,應轉而使用 go
命令來建置 Go 程式碼,並視需要改寫 makefile 來執行任何輔助建置工作。
cgo 命令
在 Go 1 中,cgo 命令 會使用不同的 _cgo_export.h
檔案,這會為含有 //export
行的套件產生。_cgo_export.h
檔案現在會從 C 前置註解開始,因此輸出的函式定義可以使用所定義的類型。這會有將前置註解編譯多次的效果,所以使用 //export
的套件不應將函式定義或變數初始化放在 C 前置註解中。
封裝的版本
與 Go 1 搭配的最重要變更之一,便是預先封裝且可下載的套件的普及。這些套件對多種架構和作業系統 (包括 Windows) 都可以使用,而且數量還會持續增加。安裝詳細資訊說明在 入門指南 網頁上,同時可以在 下載頁面 上找到套件清單。