Ghi chú phát hành Go 1.21
Giới thiệu Go 1.21
Bản phát hành Go mới nhất, phiên bản 1.21, ra mắt sáu tháng sau Go 1.20. Phần lớn thay đổi nằm ở phần triển khai của toolchain, runtime và thư viện. Như mọi khi, bản phát hành duy trì cam kết tương thích của Go 1; thực tế, Go 1.21 cải thiện cam kết đó. Chúng tôi kỳ vọng hầu như tất cả chương trình Go vẫn tiếp tục biên dịch và chạy như trước.
Go 1.21 giới thiệu một thay đổi nhỏ về cách đánh số bản phát hành.
Trước đây, chúng tôi dùng Go 1.N để chỉ cả phiên bản ngôn ngữ Go tổng thể và họ phát hành
cũng như bản phát hành đầu tiên trong họ đó.
Bắt đầu từ Go 1.21, bản phát hành đầu tiên giờ là Go 1.N.0.
Hôm nay chúng tôi phát hành cả ngôn ngữ Go 1.21 và triển khai ban đầu của nó, bản phát hành Go 1.21.0.
Các ghi chú này đề cập đến “Go 1.21”; các công cụ như go version sẽ báo cáo “go1.21.0”
(cho đến khi bạn nâng cấp lên Go 1.21.1).
Xem “Phiên bản Go” trong tài liệu “Go Toolchains” để biết chi tiết
về cách đánh số phiên bản mới.
Thay đổi ngôn ngữ
Go 1.21 thêm ba hàm built-in mới vào ngôn ngữ.
-
Các hàm mới
minvàmaxtính giá trị nhỏ nhất (hoặc lớn nhất, vớimax) trong một số lượng cố định các đối số đã cho. Xem đặc tả ngôn ngữ để biết chi tiết. -
Hàm mới
clearxóa tất cả phần tử khỏi một map hoặc đặt tất cả phần tử của một slice về zero. Xem đặc tả ngôn ngữ để biết chi tiết.
Thứ tự khởi tạo gói giờ được định nghĩa chính xác hơn. Thuật toán mới là:
- Sắp xếp tất cả gói theo đường dẫn import.
- Lặp lại cho đến khi danh sách gói trống:
- Tìm gói đầu tiên trong danh sách mà tất cả import của nó đã được khởi tạo.
- Khởi tạo gói đó và xóa nó khỏi danh sách.
Điều này có thể thay đổi hành vi của một số chương trình dựa trên thứ tự khởi tạo cụ thể không được thể hiện bằng các import tường minh. Hành vi của các chương trình như vậy không được định nghĩa rõ ràng bởi đặc tả trong các bản phát hành trước. Quy tắc mới cung cấp định nghĩa rõ ràng.
Nhiều cải tiến tăng sức mạnh và độ chính xác của suy diễn kiểu đã được thực hiện.
- Một hàm generic (có thể được khởi tạo một phần) giờ có thể được gọi với các đối số bản thân là các hàm generic (có thể được khởi tạo một phần). Compiler sẽ cố gắng suy diễn các đối số kiểu còn thiếu của callee (như trước) và, cho mỗi đối số là hàm generic không được khởi tạo đầy đủ, các đối số kiểu còn thiếu của nó (mới). Các trường hợp sử dụng điển hình là các lời gọi đến các hàm generic hoạt động trên container (như slices.IndexFunc) nơi một đối số hàm cũng có thể là generic, và nơi đối số kiểu của hàm được gọi và các đối số của nó được suy diễn từ kiểu container. Tổng quát hơn, một hàm generic giờ có thể được dùng mà không cần khởi tạo tường minh khi nó được gán cho một biến hoặc được trả về như một giá trị kết quả nếu các đối số kiểu có thể được suy diễn từ phép gán.
- Suy diễn kiểu giờ cũng xem xét các phương thức khi một giá trị được gán cho interface: các đối số kiểu cho các tham số kiểu được dùng trong chữ ký phương thức có thể được suy diễn từ các kiểu tham số tương ứng của các phương thức khớp.
- Tương tự, vì một đối số kiểu phải triển khai tất cả phương thức của ràng buộc tương ứng của nó, các phương thức của đối số kiểu và ràng buộc được khớp, có thể dẫn đến việc suy diễn các đối số kiểu bổ sung.
- Nếu nhiều đối số hằng số không được gõ thuộc các loại khác nhau (chẳng hạn một int không được gõ và một hằng số dấu phẩy động không được gõ) được truyền cho các tham số có cùng kiểu tham số kiểu (không được chỉ định khác), thay vì lỗi, suy diễn kiểu giờ xác định kiểu bằng cách tiếp cận giống như một toán tử với các toán hạng hằng số không được gõ. Thay đổi này điều chỉnh các kiểu được suy diễn từ các đối số hằng số không được gõ cho phù hợp với các kiểu của biểu thức hằng số.
- Suy diễn kiểu giờ chính xác khi khớp các kiểu tương ứng trong phép gán: các kiểu thành phần (chẳng hạn các phần tử của slice, hoặc các kiểu tham số trong chữ ký hàm) phải giống hệt nhau (cho các đối số kiểu phù hợp) để khớp, nếu không suy diễn thất bại. Thay đổi này tạo ra thông báo lỗi chính xác hơn: khi trước đây suy diễn kiểu có thể thành công không đúng và dẫn đến phép gán không hợp lệ, compiler giờ báo cáo lỗi suy diễn nếu hai kiểu không thể khớp được.
Tổng quát hơn, mô tả về suy diễn kiểu trong đặc tả ngôn ngữ đã được làm rõ. Tổng hợp lại, tất cả những thay đổi này làm cho suy diễn kiểu mạnh mẽ hơn và các lỗi suy diễn ít bất ngờ hơn.
Go 1.21 bao gồm bản xem trước về một thay đổi ngôn ngữ mà chúng tôi đang xem xét cho phiên bản Go tương lai: biến vòng lặp for thành theo từng lần lặp thay vì theo toàn bộ vòng lặp, để tránh các lỗi chia sẻ vô tình. Để biết chi tiết về cách thử thay đổi ngôn ngữ đó, xem trang wiki LoopvarExperiment.
Go 1.21 giờ định nghĩa rằng nếu một goroutine đang panic và recover được gọi trực tiếp bởi một hàm deferred,
giá trị trả về của recover được đảm bảo không phải nil. Để đảm bảo điều này, gọi panic
với giá trị interface nil (hoặc nil không được gõ) gây ra runtime panic kiểu
*runtime.PanicNilError.
Để hỗ trợ các chương trình được viết cho các phiên bản Go cũ hơn, nil panic có thể được bật lại bằng cách đặt
GODEBUG=panicnil=1.
Cài đặt này được bật tự động khi biên dịch chương trình mà main package của nó
nằm trong module khai báo go 1.20 hoặc cũ hơn.
Công cụ
Go 1.21 thêm hỗ trợ cải thiện cho tương thích ngược và tương thích tiến trong Go toolchain.
Để cải thiện tương thích ngược, Go 1.21 chính thức hóa
việc Go sử dụng biến môi trường GODEBUG để kiểm soát
hành vi mặc định cho các thay đổi không vi phạm theo
chính sách tương thích
nhưng dù sao có thể khiến các chương trình hiện tại bị hỏng.
(Ví dụ: các chương trình phụ thuộc vào hành vi có lỗi có thể bị hỏng
khi lỗi được sửa, nhưng các sửa lỗi không được coi là thay đổi vi phạm.)
Khi Go phải thực hiện loại thay đổi hành vi này,
nó giờ chọn giữa hành vi cũ và mới dựa trên
dòng go trong tệp go.work của workspace
hoặc tệp go.mod của main module.
Nâng cấp lên Go toolchain mới nhưng để dòng go
ở phiên bản Go cũ (cũ hơn) sẽ giữ nguyên hành vi của toolchain cũ.
Với hỗ trợ tương thích này, Go toolchain mới nhất luôn nên là
triển khai tốt nhất, an toàn nhất của phiên bản Go cũ.
Xem “Go, Tương thích ngược, và GODEBUG” để biết chi tiết.
Để cải thiện tương thích tiến, Go 1.21 giờ đọc dòng go
trong tệp go.work hoặc go.mod như một yêu cầu tối thiểu nghiêm ngặt: go 1.21.0 có nghĩa là
workspace hoặc module không thể dùng với Go 1.20 hoặc Go 1.21rc1.
Điều này cho phép các dự án phụ thuộc vào các bản sửa trong các phiên bản Go mới hơn
để đảm bảo họ không được dùng với các phiên bản cũ hơn.
Nó cũng cho phép báo cáo lỗi tốt hơn cho các dự án sử dụng tính năng Go mới:
khi vấn đề là cần phiên bản Go mới hơn,
vấn đề đó được báo cáo rõ ràng, thay vì cố build code
và in lỗi về import chưa giải quyết hoặc lỗi cú pháp.
Để làm cho các yêu cầu phiên bản nghiêm ngặt hơn mới này dễ quản lý hơn,
lệnh go giờ có thể gọi không chỉ toolchain
đi kèm trong bản phát hành của nó mà còn các phiên bản Go toolchain khác tìm thấy trong PATH
hoặc được tải xuống theo yêu cầu.
Nếu dòng go trong go.mod hoặc go.work
khai báo yêu cầu tối thiểu về phiên bản Go mới hơn, lệnh go
sẽ tìm và chạy phiên bản đó tự động.
Directive toolchain mới đặt toolchain tối thiểu được đề xuất để sử dụng,
có thể mới hơn tối thiểu go nghiêm ngặt.
Xem “Go Toolchains” để biết chi tiết.
Lệnh go
Cờ build -pgo giờ mặc định là -pgo=auto,
và hạn chế chỉ định một main package duy nhất trên dòng
lệnh đã được bỏ. Nếu tệp có tên default.pgo có mặt
trong thư mục của main package, lệnh go sẽ dùng
nó để bật tối ưu hóa dựa trên hồ sơ thực thi khi build chương trình tương ứng.
Cờ -C dir giờ phải là cờ đầu tiên
trên dòng lệnh khi được dùng.
Tùy chọn go test mới
-fullpath in tên đường dẫn đầy đủ trong các thông báo log test,
thay vì chỉ tên cơ sở.
Cờ go test -c giờ
hỗ trợ ghi test binary cho nhiều gói, mỗi gói vào
pkg.test nơi pkg là tên gói.
Sẽ là lỗi nếu nhiều hơn một gói test được biên dịch có tên gói đã cho.
Cờ go test -o giờ
chấp nhận đối số thư mục, trong đó các test binary được ghi vào thư mục đó
thay vì thư mục hiện tại.
Khi dùng external (C) linker với cgo được bật, gói runtime/cgo giờ được
cung cấp cho Go linker như một dependency bổ sung để đảm bảo rằng Go
runtime tương thích với bất kỳ thư viện bổ sung nào được thêm bởi C linker.
Cgo
Trong các tệp import "C", Go toolchain giờ
báo cáo đúng lỗi khi cố khai báo phương thức Go trên kiểu C.
Runtime
Khi in các stack rất sâu, runtime giờ in 50 frame đầu tiên (trong cùng) theo sau bởi 50 frame dưới cùng (ngoài cùng), thay vì chỉ in 100 frame đầu tiên. Điều này giúp dễ dàng hơn để xem cách các stack đệ quy sâu bắt đầu, và đặc biệt có giá trị để debug stack overflow.
Trên các nền tảng Linux hỗ trợ transparent huge pages, Go runtime
giờ quản lý rõ ràng hơn những phần nào của heap có thể được hỗ trợ bởi huge pages.
Điều này dẫn đến sử dụng bộ nhớ tốt hơn: các heap nhỏ
nên thấy ít bộ nhớ được sử dụng hơn (lên đến 50% trong các trường hợp cực đoan) trong khi
các heap lớn nên thấy ít huge pages bị phá vỡ hơn cho các phần dày đặc của
heap, cải thiện việc sử dụng CPU và độ trễ lên đến 1%. Hệ quả của điều này
là runtime không còn cố gắng khắc phục một cài đặt cấu hình Linux cụ thể
có vấn đề, điều này có thể dẫn đến chi phí bộ nhớ cao hơn. Cách sửa được khuyến nghị là
điều chỉnh cài đặt huge page của OS theo hướng dẫn GC.
Tuy nhiên, cũng có các giải pháp thay thế khác. Xem phần về
max_ptes_none.
Do điều chỉnh bộ gom rác bên trong runtime,
các ứng dụng có thể thấy giảm đến 40% trong độ trễ đuôi ứng dụng
và giảm nhỏ trong việc sử dụng bộ nhớ. Một số ứng dụng cũng có thể thấy
giảm nhỏ trong throughput.
Giảm sử dụng bộ nhớ nên tỷ lệ với sự giảm throughput,
sao cho đánh đổi throughput/bộ nhớ của bản phát hành trước có thể được khôi phục (với ít thay đổi về độ trễ) bằng cách
tăng GOGC và/hoặc GOMEMLIMIT một chút.
Các lời gọi từ C sang Go trên các thread được tạo trong C yêu cầu một số thiết lập để chuẩn bị cho thực thi Go. Trên các nền tảng Unix, thiết lập này giờ được giữ nguyên qua nhiều lời gọi từ cùng một thread. Điều này giảm đáng kể chi phí của các lời gọi C sang Go tiếp theo từ khoảng 1-3 microsecond mỗi lời gọi xuống còn khoảng 100-200 nanosecond mỗi lời gọi.
Compiler
Tối ưu hóa dựa trên hồ sơ thực thi (PGO), được thêm như bản xem trước trong Go 1.20, giờ sẵn sàng
để sử dụng chung. PGO bật các tối ưu hóa bổ sung trên code được xác định là
nóng bởi hồ sơ của các workload sản xuất. Như đã đề cập trong
phần lệnh Go, PGO được bật theo mặc định cho
các binary chứa hồ sơ default.pgo trong thư mục main
package. Cải thiện hiệu năng thay đổi tùy theo hành vi ứng dụng, với hầu hết các chương trình từ một tập đại diện các chương trình Go thấy
từ 2 đến 7% cải thiện khi bật PGO. Xem
hướng dẫn sử dụng PGO để biết tài liệu chi tiết.
Các build PGO giờ có thể devirtualize một số lời gọi phương thức interface, thêm lời gọi cụ thể đến callee phổ biến nhất. Điều này bật tối ưu hóa thêm, chẳng hạn như inline callee.
Go 1.21 cải thiện tốc độ build lên đến 6%, chủ yếu nhờ vào việc build compiler với PGO.
Assembler
Trên amd64, các hàm assembly frameless nosplit không còn tự động được đánh dấu là NOFRAME.
Thay vào đó, thuộc tính NOFRAME phải được chỉ định tường minh nếu muốn,
vốn đã là hành vi trên các kiến trúc khác hỗ trợ frame pointer.
Với điều này, runtime giờ duy trì các frame pointer cho quá trình chuyển đổi stack.
Trình xác minh kiểm tra việc sử dụng sai R15 khi dynamic linking trên amd64 đã được cải thiện.
Linker
Trên windows/amd64, linker (với sự trợ giúp của compiler) giờ phát ra dữ liệu SEH unwinding theo mặc định, cải thiện việc tích hợp của các ứng dụng Go với Windows debugger và các công cụ khác.
Trong Go 1.21, linker (với sự trợ giúp của compiler) giờ có khả năng xóa các biến map toàn cục chết (không được tham chiếu), nếu số mục trong bộ khởi tạo biến đủ lớn, và nếu các biểu thức khởi tạo không có tác dụng phụ.
Thư viện chuẩn
Gói log/slog mới
Gói log/slog mới cung cấp structured logging với các cấp độ. Structured logging phát ra các cặp khóa-giá trị để cho phép xử lý nhanh, chính xác các lượng lớn dữ liệu log. Gói hỗ trợ tích hợp với các công cụ và dịch vụ phân tích log phổ biến.
Gói testing/slogtest mới
Gói testing/slogtest mới có thể giúp xác nhận các triển khai slog.Handler.
Gói slices mới
Gói slices mới cung cấp nhiều thao tác thông thường trên các slice, sử dụng các hàm generic hoạt động với slice của bất kỳ kiểu phần tử nào.
Gói maps mới
Gói maps mới cung cấp một số thao tác thông thường trên các map, sử dụng các hàm generic hoạt động với các map của bất kỳ kiểu khóa hoặc phần tử nào.
Gói cmp mới
Gói cmp mới định nghĩa ràng buộc kiểu
Ordered và
hai hàm generic mới
Less
và Compare hữu ích với các
kiểu có thứ tự.
Các thay đổi nhỏ trong thư viện
Như mọi khi, có nhiều thay đổi và cập nhật nhỏ trong thư viện, được thực hiện với cam kết tương thích của Go 1 được ghi nhớ. Ngoài ra cũng có nhiều cải thiện hiệu năng, không được liệt kê ở đây.
archive/tar
Triển khai interface
io/fs.FileInfo
được trả bởi
Header.FileInfo
giờ triển khai phương thức String gọi
io/fs.FormatFileInfo.
archive/zip
Triển khai interface
io/fs.FileInfo
được trả bởi
FileHeader.FileInfo
giờ triển khai phương thức String gọi
io/fs.FormatFileInfo.
Triển khai interface
io/fs.DirEntry
được trả bởi phương thức
io/fs.ReadDirFile.ReadDir
của
io/fs.File
được trả bởi
Reader.Open
giờ triển khai phương thức String gọi
io/fs.FormatDirEntry.
bytes
Kiểu Buffer
có hai phương thức mới:
Available
và AvailableBuffer.
Chúng có thể dùng cùng với phương thức
Write
để append trực tiếp vào Buffer.
context
Hàm mới WithoutCancel
trả về bản sao của một context không bị hủy khi context gốc
bị hủy.
Các hàm mới WithDeadlineCause
và WithTimeoutCause
cung cấp cách đặt nguyên nhân hủy context khi deadline hoặc
bộ đếm thời gian hết hạn. Nguyên nhân có thể lấy lại bằng hàm
Cause.
Hàm mới AfterFunc
đăng ký một hàm chạy sau khi context bị hủy.
Một tối ưu hóa có nghĩa là kết quả của việc gọi
Background
và TODO và
chuyển đổi chúng sang một kiểu dùng chung có thể được coi là bằng nhau.
Trong các bản phát hành trước chúng luôn khác nhau. So sánh
các giá trị Context
cho tính bằng nhau chưa bao giờ được định nghĩa rõ ràng, vì vậy đây không
được coi là thay đổi không tương thích.
crypto/ecdsa
PublicKey.Equal và
PrivateKey.Equal
giờ thực thi trong thời gian không đổi.
crypto/elliptic
Tất cả phương thức Curve đã bị deprecated, cùng với GenerateKey, Marshal, và Unmarshal. Cho các thao tác ECDH, nên dùng gói crypto/ecdh mới thay thế. Cho các thao tác cấp thấp hơn, hãy dùng các module bên thứ ba như filippo.io/nistec.
crypto/rand
Gói crypto/rand giờ dùng system call getrandom trên NetBSD 10.0 trở lên.
crypto/rsa
Hiệu năng của các phép tính RSA riêng (giải mã và ký) giờ tốt hơn Go 1.19 cho GOARCH=amd64 và GOARCH=arm64. Nó đã bị thoái lui trong Go 1.20.
Do việc thêm các trường riêng vào PrecomputedValues, PrivateKey.Precompute phải được gọi để có hiệu năng tối ưu ngay cả khi deserializing (ví dụ từ JSON) một khóa riêng đã được tính trước.
PublicKey.Equal và
PrivateKey.Equal
giờ thực thi trong thời gian không đổi.
Hàm GenerateMultiPrimeKey và trường PrecomputedValues.CRTValues đã bị deprecated. PrecomputedValues.CRTValues vẫn sẽ được điền khi PrivateKey.Precompute được gọi, nhưng các giá trị sẽ không được sử dụng trong quá trình giải mã.
crypto/sha256
Các phép tính SHA-224 và SHA-256 giờ dùng các hướng dẫn native khi có sẵn với GOARCH=amd64, cải thiện hiệu năng khoảng 3-4 lần.
crypto/tls
Các máy chủ giờ bỏ qua việc xác minh chứng chỉ client (bao gồm không chạy
Config.VerifyPeerCertificate)
cho các kết nối được tiếp tục, ngoài việc kiểm tra thời gian hết hạn. Điều này làm cho
session ticket lớn hơn khi chứng chỉ client được sử dụng. Các client đã
bỏ qua việc xác minh khi tiếp tục, nhưng giờ kiểm tra thời gian hết hạn
ngay cả khi Config.InsecureSkipVerify
được đặt.
Các ứng dụng giờ có thể kiểm soát nội dung của session ticket.
- Kiểu mới
SessionStatemô tả một phiên có thể tiếp tục. - Phương thức
SessionState.Bytesvà hàmParseSessionStateserialize và deserialize mộtSessionState. - Các hook
Config.WrapSessionvàConfig.UnwrapSessionchuyển đổiSessionStatethành và từ ticket ở phía máy chủ. - Các phương thức
Config.EncryptTicketvàConfig.DecryptTicketcung cấp triển khai mặc định củaWrapSessionvàUnwrapSession. - Phương thức
ClientSessionState.ResumptionStatevà hàmNewResumptionStatecó thể được dùng bởi triển khaiClientSessionCacheđể lưu trữ và tiếp tục các phiên ở phía client.
Để giảm khả năng session ticket được dùng như cơ chế theo dõi
giữa các kết nối, máy chủ giờ phát hành ticket mới ở mỗi
lần tiếp tục (nếu chúng được hỗ trợ và không bị tắt) và ticket không còn mang
định danh cho khóa mã hóa chúng nữa. Nếu truyền số lượng lớn
khóa cho Conn.SetSessionTicketKeys,
điều này có thể dẫn đến chi phí hiệu năng đáng chú ý.
Cả client và máy chủ giờ triển khai extension Extended Master Secret (RFC 7627).
Việc deprecated của ConnectionState.TLSUnique
đã được hoàn nguyên, và giờ được đặt cho các kết nối được tiếp tục hỗ trợ Extended Master Secret.
Kiểu mới QUICConn
cung cấp hỗ trợ cho các triển khai QUIC, bao gồm hỗ trợ 0-RTT. Lưu ý
rằng đây không tự nó là triển khai QUIC, và 0-RTT vẫn chưa
được hỗ trợ trong TLS.
Hàm mới VersionName
trả về tên cho một số phiên bản TLS.
Các mã cảnh báo TLS được gửi từ máy chủ cho các lỗi xác thực client đã được cải thiện. Trước đây, các lỗi này luôn dẫn đến cảnh báo “bad certificate”. Giờ, một số lỗi sẽ dẫn đến các mã cảnh báo phù hợp hơn, được định nghĩa bởi RFC 5246 và RFC 8446:
- Cho các kết nối TLS 1.3, nếu máy chủ được cấu hình yêu cầu xác thực client bằng RequireAnyClientCert hoặc RequireAndVerifyClientCert, và client không cung cấp bất kỳ chứng chỉ nào, máy chủ giờ sẽ trả về cảnh báo “certificate required”.
- Nếu client cung cấp chứng chỉ không được ký bởi tập hợp CA tin cậy được cấu hình trên máy chủ, máy chủ sẽ trả về cảnh báo “unknown certificate authority”.
- Nếu client cung cấp chứng chỉ đã hết hạn hoặc chưa có hiệu lực, máy chủ sẽ trả về cảnh báo “expired certificate”.
- Trong tất cả các tình huống khác liên quan đến lỗi xác thực client, máy chủ vẫn trả về “bad certificate”.
crypto/x509
RevocationList.RevokedCertificates đã bị deprecated và được thay thế bằng trường RevokedCertificateEntries mới, là một slice của RevocationListEntry. RevocationListEntry chứa tất cả các trường trong pkix.RevokedCertificate, cũng như mã lý do thu hồi.
Các ràng buộc tên giờ được thực thi đúng cách trên các chứng chỉ không phải leaf, và không áp dụng cho các chứng chỉ nơi chúng được biểu đạt.
debug/elf
Phương thức mới
File.DynValue
có thể dùng để lấy các giá trị số được liệt kê với một
dynamic tag đã cho.
Các cờ hằng số được phép trong dynamic tag DT_FLAGS_1
giờ được định nghĩa với kiểu
DynFlag1. Các tag này
có tên bắt đầu bằng DF_1.
Gói giờ định nghĩa hằng số
COMPRESS_ZSTD.
Gói giờ định nghĩa hằng số
R_PPC64_REL24_P9NOTOC.
debug/pe
Các lần thử đọc từ một phần chứa dữ liệu chưa khởi tạo
bằng cách dùng
Section.Data
hoặc reader được trả bởi Section.Open
giờ trả về lỗi.
embed
io/fs.File
được trả bởi
FS.Open giờ
có phương thức ReadAt triển khai
io.ReaderAt.
Gọi FS.Open.Stat
sẽ trả về một kiểu giờ triển khai phương thức String
gọi
io/fs.FormatFileInfo.
encoding/binary
Biến mới
NativeEndian
có thể dùng để chuyển đổi giữa byte slice và số nguyên
sử dụng endianness native của máy hiện tại.
errors
Lỗi mới
ErrUnsupported
cung cấp cách chuẩn hóa để cho biết rằng một
thao tác được yêu cầu có thể không được thực hiện vì nó không được hỗ trợ.
Ví dụ: lời gọi đến
os.Link khi sử dụng hệ thống tệp không hỗ trợ hard link.
flag
Hàm mới BoolFunc
và phương thức
FlagSet.BoolFunc
định nghĩa một flag không yêu cầu đối số và gọi
một hàm khi flag được sử dụng. Điều này tương tự như
Func nhưng cho boolean flag.
Định nghĩa flag
(qua Bool,
BoolVar,
Int,
IntVar, v.v.)
sẽ panic nếu Set đã
được gọi trên một flag có cùng tên. Thay đổi này được thiết kế
để phát hiện các trường hợp thay đổi trong
thứ tự khởi tạo gây ra các thao tác flag xảy ra theo
thứ tự khác với mong đợi. Trong nhiều trường hợp, cách sửa vấn đề
này là giới thiệu một dependency gói tường minh để
sắp xếp đúng việc định nghĩa trước bất kỳ
thao tác Set nào.
go/ast
Predicate mới IsGenerated
báo cáo liệu một cây cú pháp tệp có chứa
comment đặc biệt
theo quy ước cho biết tệp được tạo bởi một công cụ hay không.
Trường mới
File.GoVersion
ghi lại phiên bản Go tối thiểu yêu cầu bởi
bất kỳ directive //go:build hoặc // +build nào.
go/build
Gói giờ phân tích các build directive (comment bắt đầu
bằng //go:) trong header tệp (trước
khai báo package). Các directive này
có sẵn trong các trường mới
Package
Directives,
TestDirectives,
và
XTestDirectives.
go/build/constraint
Hàm mới
GoVersion
trả về phiên bản Go tối thiểu được ngụ ý bởi một biểu thức build.
go/token
Phương thức mới File.Lines
trả về bảng số dòng của tệp theo cùng dạng được chấp nhận bởi
File.SetLines.
go/types
Phương thức mới Package.GoVersion
trả về phiên bản ngôn ngữ Go được dùng để kiểm tra gói.
hash/maphash
Gói hash/maphash giờ có triển khai Go thuần túy, có thể chọn bằng build tag purego.
html/template
Lỗi mới
ErrJSTemplate
được trả khi một action xuất hiện trong JavaScript template
literal. Trước đây một lỗi không được export sẽ được trả về.
io/fs
Hàm mới
FormatFileInfo
trả về phiên bản được định dạng của
FileInfo.
Hàm mới
FormatDirEntry
trả về phiên bản được định dạng của
DirEntry.
Triển khai của
DirEntry
được trả bởi
ReadDir giờ
triển khai phương thức String gọi
FormatDirEntry,
và tương tự với
giá trị DirEntry
được truyền cho
WalkDirFunc.
math/big
Phương thức mới Int.Float64
trả về giá trị dấu phẩy động gần nhất với
số nguyên đa độ chính xác, cùng với thông tin về bất kỳ
làm tròn nào đã xảy ra.
net
Trên Linux, gói net giờ có thể dùng
Multipath TCP khi kernel hỗ trợ nó. Nó không được dùng
theo mặc định. Để dùng Multipath TCP khi có sẵn trên client, hãy gọi
phương thức
Dialer.SetMultipathTCP
trước khi gọi phương thức
Dialer.Dial hoặc
Dialer.DialContext.
Để dùng Multipath TCP khi có sẵn trên máy chủ, hãy gọi
phương thức
ListenConfig.SetMultipathTCP
trước khi gọi phương thức
ListenConfig.Listen.
Chỉ định network là "tcp" hoặc
"tcp4" hoặc "tcp6" như thường lệ. Nếu
Multipath TCP không được kernel hoặc remote host hỗ trợ,
kết nối sẽ lặng lẽ fall back về TCP. Để kiểm tra liệu một
kết nối cụ thể có đang sử dụng Multipath TCP hay không, hãy dùng phương thức
TCPConn.MultipathTCP.
Trong bản phát hành Go tương lai, chúng tôi có thể bật Multipath TCP theo mặc định trên các hệ thống hỗ trợ nó.
net/http
Phương thức mới ResponseController.EnableFullDuplex
cho phép các handler máy chủ đọc đồng thời từ body yêu cầu HTTP/1
trong khi viết phản hồi. Thông thường, HTTP/1 server
tự động tiêu thụ bất kỳ body yêu cầu còn lại nào trước khi bắt đầu
viết phản hồi, để tránh deadlock client cố viết yêu cầu đầy đủ trước khi đọc phản hồi.
Phương thức EnableFullDuplex tắt hành vi này.
Lỗi mới ErrSchemeMismatch được trả bởi Client và Transport khi máy chủ phản hồi yêu cầu HTTPS bằng phản hồi HTTP.
Gói net/http giờ hỗ trợ
errors.ErrUnsupported,
sao cho biểu thức
errors.Is(http.ErrNotSupported, errors.ErrUnsupported)
sẽ trả về true.
os
Các chương trình giờ có thể truyền giá trị time.Time rỗng cho
hàm Chtimes
để giữ nguyên thời gian truy cập hoặc thời gian sửa đổi.
Trên Windows,
phương thức File.Chdir
giờ thay đổi thư mục hiện tại thành tệp, thay vì
luôn trả về lỗi.
Trên các hệ thống Unix, nếu descriptor không chặn được truyền
cho NewFile, gọi
phương thức File.Fd
giờ sẽ trả về descriptor không chặn. Trước đây
descriptor được chuyển đổi sang chế độ blocking.
Trên Windows, gọi
Truncate trên
tệp không tồn tại trước đây tạo tệp rỗng. Giờ nó trả về
lỗi cho biết tệp không tồn tại.
Trên Windows, gọi
TempDir giờ dùng
GetTempPath2W khi có sẵn, thay vì GetTempPathW.
Hành vi mới là biện pháp tăng cường bảo mật ngăn chặn
các tệp tạm thời được tạo bởi các quá trình chạy với tư cách SYSTEM
bị truy cập bởi các quá trình không phải SYSTEM.
Trên Windows, gói os giờ hỗ trợ làm việc với các tệp có tên, được lưu trữ dưới dạng UTF-16, không thể được biểu diễn dưới dạng UTF-8 hợp lệ.
Trên Windows, Lstat giờ giải quyết
symbolic link cho các đường dẫn kết thúc bằng dấu phân cách đường dẫn, nhất quán với hành vi của nó
trên các nền tảng POSIX.
Triển khai interface
io/fs.DirEntry
được trả bởi hàm ReadDir và
phương thức File.ReadDir
giờ triển khai phương thức String gọi
io/fs.FormatDirEntry.
Triển khai interface
io/fs.FS được trả bởi
hàm DirFS giờ triển khai
các interface io/fs.ReadFileFS và
io/fs.ReadDirFS.
path/filepath
Triển khai interface
io/fs.DirEntry
được truyền cho đối số hàm của
WalkDir
giờ triển khai phương thức String gọi
io/fs.FormatDirEntry.
reflect
Trong Go 1.21, ValueOf
không còn ép buộc đối số của nó được cấp phát trên heap, cho phép
nội dung của Value được cấp phát trên stack. Hầu hết
các thao tác trên Value cũng cho phép giá trị bên dưới
được cấp phát trên stack.
Phương thức Value mới
Value.Clear
xóa nội dung của map hoặc đặt nội dung của slice về zero.
Điều này tương ứng với hàm built-in clear mới
được thêm vào ngôn ngữ.
Các kiểu SliceHeader
và StringHeader
giờ bị deprecated. Trong code mới, ưu tiên dùng
unsafe.Slice,
unsafe.SliceData,
unsafe.String,
hoặc unsafe.StringData.
regexp
Regexp giờ định nghĩa
các phương thức MarshalText
và UnmarshalText.
Chúng triển khai
encoding.TextMarshaler
và
encoding.TextUnmarshaler
và sẽ được dùng bởi các gói như
encoding/json.
runtime
Các stack trace dạng văn bản được tạo bởi chương trình Go, chẳng hạn như
những gì được tạo khi crash, gọi runtime.Stack, hoặc
thu thập goroutine profile với debug=2, giờ
bao gồm ID của các goroutine đã tạo mỗi goroutine trong
stack trace.
Các ứng dụng Go bị crash giờ có thể opt-in vào Windows Error Reporting (WER) bằng cách đặt biến môi trường
GOTRACEBACK=wer hoặc gọi debug.SetTraceback("wer")
trước khi crash. Ngoài việc bật WER, runtime sẽ hoạt động như với GOTRACEBACK=crash.
Trên các hệ thống không phải Windows, GOTRACEBACK=wer bị bỏ qua.
GODEBUG=cgocheck=2, một trình kiểm tra kỹ lưỡng các quy tắc truyền con trỏ cgo,
không còn có sẵn như một tùy chọn debug nữa.
Thay vào đó, nó có sẵn như một thử nghiệm sử dụng GOEXPERIMENT=cgocheck2.
Đặc biệt điều này có nghĩa là chế độ này phải được chọn tại thời điểm build thay vì thời gian khởi động.
GODEBUG=cgocheck=1 vẫn có sẵn (và vẫn là mặc định).
Kiểu mới Pinner đã được thêm vào gói
runtime. Pinner có thể dùng để “pin” bộ nhớ Go
để nó có thể được sử dụng tự do hơn bởi code không phải Go. Ví dụ:
truyền các giá trị Go tham chiếu đến bộ nhớ Go được pin cho code C giờ
được cho phép. Trước đây, truyền bất kỳ tham chiếu lồng nhau nào như vậy
bị cấm bởi
quy tắc truyền con trỏ cgo.
Xem tài liệu để biết thêm chi tiết.
runtime/metrics
Một số metric GC nội bộ trước đây, như kích thước live heap, giờ
có sẵn.
GOGC và GOMEMLIMIT cũng giờ
có sẵn như metric.
runtime/trace
Thu thập trace trên amd64 và arm64 giờ phát sinh chi phí CPU nhỏ hơn đáng kể: cải thiện lên đến 10 lần so với bản phát hành trước.
Các trace giờ chứa các sự kiện stop-the-world tường minh cho mỗi lý do Go runtime có thể stop-the-world, không chỉ bộ gom rác.
sync
Các hàm mới OnceFunc,
OnceValue, và
OnceValues
nắm bắt một cách sử dụng phổ biến của Once để
khởi tạo lười biếng một giá trị khi sử dụng lần đầu.
syscall
Trên Windows,
hàm Fchdir
giờ thay đổi thư mục hiện tại thành đối số của nó, thay vì
luôn trả về lỗi.
Trên FreeBSD,
SysProcAttr
có trường mới Jail có thể dùng để đặt
tiến trình mới tạo vào môi trường jail.
Trên Windows, gói syscall giờ hỗ trợ làm việc với các tệp có
tên, được lưu trữ dưới dạng UTF-16, không thể được biểu diễn dưới dạng UTF-8 hợp lệ.
Các hàm UTF16ToString
và UTF16FromString
giờ chuyển đổi giữa dữ liệu UTF-16 và
chuỗi WTF-8.
Điều này tương thích ngược vì WTF-8 là siêu tập của định dạng UTF-8
được dùng trong các bản phát hành trước.
Một số giá trị lỗi khớp với
errors.ErrUnsupported mới,
sao cho errors.Is(err, errors.ErrUnsupported)
trả về true.
ENOSYSENOTSUPEOPNOTSUPPEPLAN9(chỉ Plan 9)ERROR_CALL_NOT_IMPLEMENTED(chỉ Windows)ERROR_NOT_SUPPORTED(chỉ Windows)EWINDOWS(chỉ Windows)
testing
Tùy chọn mới -test.fullpath sẽ in tên đường dẫn đầy đủ
trong các thông báo log test, thay vì chỉ tên cơ sở.
Hàm mới Testing báo cáo liệu chương trình có phải là test được tạo bởi go test hay không.
testing/fstest
Gọi Open.Stat
sẽ trả về một kiểu giờ triển khai phương thức String
gọi
io/fs.FormatFileInfo.
unicode
Gói unicode và
hỗ trợ liên quan trong toàn bộ hệ thống đã được nâng cấp lên
Unicode 15.0.0.
Các nền tảng
Darwin
Như đã thông báo trong ghi chú phát hành Go 1.20, Go 1.21 yêu cầu macOS 10.15 Catalina trở lên; hỗ trợ các phiên bản trước đã bị ngừng.
Windows
Như đã thông báo trong ghi chú phát hành Go 1.20, Go 1.21 yêu cầu ít nhất Windows 10 hoặc Windows Server 2016; hỗ trợ các phiên bản trước đã bị ngừng.
ARM
Khi build bản phân phối Go với GOARCH=arm khi không chạy
trên hệ thống ARM (tức là khi build cross-compiler sang ARM), giá trị
mặc định cho biến môi trường GOARM giờ luôn được đặt
thành 7.
Trước đây giá trị mặc định phụ thuộc vào đặc điểm của hệ thống build.
Khi không build cross-compiler, giá trị mặc định được xác định bằng cách kiểm tra hệ thống build. Điều đó đúng trước đây và vẫn đúng trong Go 1.21. Điều đã thay đổi là hành vi khi build cross-compiler.
WebAssembly
Directive go:wasmimport mới giờ có thể được dùng trong chương trình Go
để import các hàm từ WebAssembly host.
Go scheduler giờ tương tác hiệu quả hơn nhiều với JavaScript event loop, đặc biệt trong các ứng dụng chặn thường xuyên trên các sự kiện bất đồng bộ.
WebAssembly System Interface
Go 1.21 thêm một cổng thử nghiệm cho
WebAssembly System Interface (WASI), Preview 1
(GOOS=wasip1, GOARCH=wasm).
Kết quả của việc thêm giá trị GOOS mới
“wasip1”, các tệp Go có tên *_wasip1.go
giờ sẽ bị bỏ qua
bởi các công cụ Go ngoại trừ khi giá trị GOOS đó đang được
sử dụng.
Nếu bạn có tên tệp hiện có khớp với mẫu đó, bạn sẽ
cần đổi tên chúng.
ppc64/ppc64le
Trên Linux, GOPPC64=power10 giờ tạo các hướng dẫn PC-relative, hướng dẫn có tiền tố,
và các hướng dẫn Power10 mới khác. Trên AIX, GOPPC64=power10
tạo các hướng dẫn Power10, nhưng không tạo các hướng dẫn PC-relative.
Khi build các binary position-independent cho GOPPC64=power10
GOOS=linux GOARCH=ppc64le, người dùng có thể thấy kích thước binary giảm
trong hầu hết các trường hợp, trong một số trường hợp là 3.5%. Các binary position-independent được build cho
ppc64le với các giá trị -buildmode sau:
c-archive, c-shared, shared, pie, plugin.
loong64
Cổng linux/loong64 giờ hỗ trợ -buildmode=c-archive,
-buildmode=c-shared và -buildmode=pie.