Ghi chú phát hành Go 1.20

Giới thiệu Go 1.20

Bản phát hành Go mới nhất, phiên bản 1.20, ra mắt sáu tháng sau Go 1.19. 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. 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.

Thay đổi ngôn ngữ

Go 1.20 bao gồm bốn thay đổi ngôn ngữ.

Go 1.17 đã thêm chuyển đổi từ slice sang con trỏ mảng. Go 1.20 mở rộng điều này để cho phép chuyển đổi từ slice sang mảng: với một slice x, giờ có thể viết [4]byte(x) thay vì *(*[4]byte)(x).

Gói unsafe định nghĩa ba hàm mới: SliceData, String, và StringData. Cùng với Slice từ Go 1.17, các hàm này giờ cung cấp khả năng hoàn chỉnh để xây dựng và phân tách giá trị slice và string mà không phụ thuộc vào biểu diễn nội bộ của chúng.

Đặc tả ngôn ngữ giờ định nghĩa rằng giá trị struct được so sánh từng trường một, theo thứ tự các trường xuất hiện trong định nghĩa kiểu struct, và dừng lại ở sự khác biệt đầu tiên. Trước đây đặc tả có thể hiểu theo nghĩa rằng tất cả các trường cần được so sánh kể cả sau sự khác biệt đầu tiên. Tương tự, đặc tả giờ định nghĩa rằng giá trị mảng được so sánh từng phần tử một, theo thứ tự chỉ số tăng dần. Trong cả hai trường hợp, sự khác biệt này ảnh hưởng đến việc liệu một số phép so sánh nhất định có phải panic hay không. Các chương trình hiện tại không thay đổi: cách diễn đạt mới trong đặc tả mô tả những gì các triển khai đã luôn làm.

Các kiểu comparable (như interface thông thường) giờ có thể thỏa mãn ràng buộc comparable, ngay cả khi các đối số kiểu không strictly comparable (phép so sánh có thể panic khi chạy). Điều này cho phép khởi tạo một tham số kiểu bị ràng buộc bởi comparable (ví dụ: tham số kiểu cho khóa map generic do người dùng định nghĩa) với một đối số kiểu không strictly comparable như kiểu interface, hoặc kiểu tổng hợp chứa kiểu interface.

Các nền tảng

Windows

Go 1.20 là bản phát hành cuối cùng chạy trên mọi phiên bản Windows 7, 8, Server 2008 và Server 2012. Go 1.21 sẽ yêu cầu ít nhất Windows 10 hoặc Server 2016.

Darwin và iOS

Go 1.20 là bản phát hành cuối cùng chạy trên macOS 10.13 High Sierra hoặc 10.14 Mojave. Go 1.21 sẽ yêu cầu macOS 10.15 Catalina trở lên.

FreeBSD/RISC-V

Go 1.20 thêm hỗ trợ thử nghiệm cho FreeBSD trên RISC-V (GOOS=freebsd, GOARCH=riscv64).

Công cụ

Lệnh go

Thư mục $GOROOT/pkg không còn lưu trữ các gói thư viện chuẩn được biên dịch sẵn nữa: go install không còn ghi chúng, go build không còn kiểm tra chúng, và bản phân phối Go không còn đóng gói chúng. Thay vào đó, các gói trong thư viện chuẩn được biên dịch khi cần và lưu vào build cache, giống như các gói ngoài GOROOT. Thay đổi này giảm kích thước bản phân phối Go và cũng tránh sai lệch C toolchain cho các gói sử dụng cgo.

Triển khai của go test -json đã được cải thiện để ổn định hơn. Các chương trình chạy go test -json không cần cập nhật gì. Các chương trình gọi trực tiếp go tool test2json giờ nên chạy test binary với -v=test2json (ví dụ: go test -v=test2json hoặc ./pkg.test -test.v=test2json) thay vì chỉ -v.

Thay đổi liên quan đến go test -json là việc thêm một sự kiện với Action được đặt thành start ở đầu quá trình thực thi mỗi chương trình test. Khi chạy nhiều test bằng lệnh go, các sự kiện start này được đảm bảo phát ra theo cùng thứ tự với các gói được đặt tên trên dòng lệnh.

Lệnh go giờ định nghĩa các build tag theo tính năng kiến trúc, chẳng hạn amd64.v2, để cho phép chọn tệp triển khai gói dựa trên sự có mặt hoặc vắng mặt của một tính năng kiến trúc cụ thể. Xem go help buildconstraint để biết chi tiết.

Các lệnh con go giờ chấp nhận -C <dir> để chuyển thư mục làm việc sang <dir> trước khi thực hiện lệnh, có thể hữu ích cho các script cần thực thi lệnh trong nhiều module khác nhau.

Các lệnh go buildgo test không còn chấp nhận cờ -i nữa, vốn đã bị deprecated từ Go 1.16.

Lệnh go generate giờ chấp nhận -skip <pattern> để bỏ qua các directive //go:generate khớp với <pattern>.

Lệnh go test giờ chấp nhận -skip <pattern> để bỏ qua các test, subtest hoặc example khớp với <pattern>.

Khi main module nằm trong GOPATH/src, go install không còn cài đặt thư viện cho các gói không phải main vào GOPATH/pkg, và go list không còn báo cáo trường Target cho các gói đó nữa. (Trong chế độ module, các gói đã biên dịch chỉ được lưu trong build cache, nhưng một lỗi đã khiến các đích cài đặt GOPATH vẫn còn hiệu lực một cách không mong muốn.)

Các lệnh go build, go install, và các lệnh liên quan đến build giờ hỗ trợ cờ -pgo bật tối ưu hóa dựa trên hồ sơ thực thi, được mô tả chi tiết hơn trong phần Compiler bên dưới. Cờ -pgo chỉ định đường dẫn tệp hồ sơ. Khi dùng -pgo=auto, lệnh go sẽ tìm kiếm tệp tên default.pgo trong thư mục của main package và sử dụng nếu có. Chế độ này hiện yêu cầu chỉ định một main package duy nhất trên dòng lệnh, nhưng chúng tôi có kế hoạch bỏ hạn chế này trong bản phát hành tương lai. Khi dùng -pgo=off sẽ tắt tối ưu hóa dựa trên hồ sơ thực thi.

Các lệnh go build, go install, và các lệnh liên quan đến build giờ hỗ trợ cờ -cover để biên dịch đích đã chỉ định cùng với đo đạc độ phủ code. Điều này được mô tả chi tiết hơn trong phần Cover bên dưới.

go version

Lệnh go version -m giờ hỗ trợ đọc nhiều loại Go binary hơn, đặc biệt là Windows DLL được xây dựng với go build -buildmode=c-shared và Linux binary không có quyền thực thi.

Cgo

Lệnh go giờ mặc định tắt cgo trên các hệ thống không có C toolchain. Cụ thể hơn, khi biến môi trường CGO_ENABLED không được đặt, biến môi trường CC không được đặt, và trình biên dịch C mặc định (thường là clang hoặc gcc) không tìm thấy trong PATH, CGO_ENABLED mặc định là 0. Như mọi khi, bạn có thể ghi đè giá trị mặc định bằng cách đặt CGO_ENABLED tường minh.

Tác động quan trọng nhất của thay đổi mặc định này là khi Go được cài đặt trên hệ thống không có trình biên dịch C, nó giờ sẽ sử dụng bản build Go thuần túy cho các gói trong thư viện chuẩn có sử dụng cgo, thay vì dùng các gói đã phân phối sẵn (đã bị xóa, như đã lưu ý ở trên) hoặc cố gắng sử dụng cgo và thất bại. Điều này giúp Go hoạt động tốt hơn trong một số môi trường container tối giản cũng như trên macOS, nơi các gói phân phối sẵn đã không được dùng cho các gói dựa trên cgo kể từ Go 1.16.

Các gói trong thư viện chuẩn sử dụng cgo là net, os/user, và plugin. Trên macOS, các gói netos/user đã được viết lại để không dùng cgo: code giống nhau giờ được dùng cho cả build có cgo và không có cgo, cũng như cross-compiled build. Trên Windows, các gói netos/user chưa bao giờ dùng cgo. Trên các hệ thống khác, các build với cgo bị tắt sẽ sử dụng phiên bản Go thuần túy của các gói này.

Hệ quả là, trên macOS, nếu code Go sử dụng gói net được build với -buildmode=c-archive, việc liên kết archive kết quả vào chương trình C yêu cầu truyền -lresolv khi liên kết code C.

Trên macOS, race detector đã được viết lại để không dùng cgo: các chương trình bật race detector có thể được build và chạy mà không cần Xcode. Trên Linux và các hệ thống Unix khác, cũng như Windows, cần có C toolchain của máy chủ để sử dụng race detector.

Cover

Go 1.20 hỗ trợ thu thập dữ liệu phủ code cho chương trình (ứng dụng và test tích hợp), chứ không chỉ unit test.

Để thu thập dữ liệu phủ code cho một chương trình, hãy build nó với cờ -cover của go build, sau đó chạy binary kết quả với biến môi trường GOCOVERDIR được đặt thành thư mục đầu ra cho các hồ sơ phủ code. Xem trang landing ‘coverage for integration tests’ để biết cách bắt đầu. Để biết chi tiết về thiết kế và triển khai, xem đề xuất.

Vet

Phát hiện tốt hơn việc capture biến vòng lặp bởi hàm lồng nhau

Công cụ vet giờ báo cáo các tham chiếu đến biến vòng lặp theo sau lệnh gọi T.Parallel() trong thân hàm subtest. Các tham chiếu như vậy có thể quan sát giá trị của biến từ một lần lặp khác (thường gây ra các trường hợp test bị bỏ qua) hoặc trạng thái không hợp lệ do truy cập đồng thời không đồng bộ.

Công cụ cũng phát hiện lỗi tham chiếu ở nhiều nơi hơn. Trước đây nó chỉ xem xét câu lệnh cuối cùng của thân vòng lặp, nhưng giờ nó kiểm tra đệ quy các câu lệnh cuối cùng trong các câu lệnh if, switch và select.

Chuẩn đoán mới cho định dạng thời gian sai

Công cụ vet giờ báo cáo việc sử dụng định dạng thời gian 2006-02-01 (yyyy-dd-mm) với Time.Formattime.Parse. Định dạng này không xuất hiện trong các chuẩn ngày phổ biến, nhưng thường bị sử dụng nhầm khi cố dùng định dạng ngày ISO 8601 (yyyy-mm-dd).

Runtime

Một số cấu trúc dữ liệu nội bộ của bộ gom rác đã được tổ chức lại để hiệu quả hơn cả về không gian lẫn CPU. Thay đổi này giảm chi phí bộ nhớ và cải thiện hiệu năng CPU tổng thể lên đến 2%.

Bộ gom rác hoạt động ít thất thường hơn liên quan đến goroutine assist trong một số trường hợp.

Go 1.20 thêm gói runtime/coverage mới chứa các API để ghi dữ liệu hồ sơ phủ code khi chạy từ các chương trình dài hạn và/hoặc máy chủ không kết thúc qua os.Exit().

Compiler

Go 1.20 thêm hỗ trợ xem trước cho tối ưu hóa dựa trên hồ sơ thực thi (PGO). PGO cho phép toolchain thực hiện các tối ưu hóa đặc thù theo ứng dụng và khối lượng công việc dựa trên thông tin hồ sơ khi chạy. Hiện tại, compiler hỗ trợ hồ sơ CPU pprof, có thể thu thập qua các cách thông thường, chẳng hạn gói runtime/pprof hoặc net/http/pprof. Để bật PGO, truyền đường dẫn tệp hồ sơ pprof qua cờ -pgo cho go build, như đã đề cập ở trên. Go 1.20 sử dụng PGO để inline tích cực hơn các hàm tại các điểm gọi nóng. Benchmark cho một tập đại diện các chương trình Go cho thấy bật tối ưu hóa inline dựa trên hồ sơ cải thiện hiệu năng khoảng 3-4%. Xem hướng dẫn sử dụng PGO để biết tài liệu chi tiết. Chúng tôi có kế hoạch thêm nhiều tối ưu hóa dựa trên hồ sơ hơn trong các bản phát hành tương lai. Lưu ý rằng tối ưu hóa dựa trên hồ sơ là tính năng xem trước, vì vậy hãy sử dụng với sự thận trọng phù hợp.

Compiler Go 1.20 đã nâng cấp frontend để sử dụng cách xử lý dữ liệu nội bộ mới, vốn sửa một số vấn đề liên quan đến kiểu generic và cho phép khai báo kiểu trong các hàm và phương thức generic.

Compiler giờ từ chối các vòng lặp interface ẩn danh bằng lỗi compiler theo mặc định. Chúng phát sinh từ các cách dùng phức tạp của embedded interface và luôn có vấn đề về tính đúng đắn tinh tế, nhưng chúng tôi không có bằng chứng về việc chúng được dùng trong thực tế. Giả sử không có báo cáo từ người dùng bị ảnh hưởng xấu bởi thay đổi này, chúng tôi có kế hoạch cập nhật đặc tả ngôn ngữ cho Go 1.22 để cấm chúng một cách chính thức để các tác giả công cụ cũng có thể dừng hỗ trợ chúng.

Go 1.18 và 1.19 có sự thoái lui về tốc độ build, chủ yếu do việc thêm hỗ trợ generics và các công việc tiếp theo. Go 1.20 cải thiện tốc độ build lên đến 10%, đưa nó trở lại ngang với Go 1.17. So với Go 1.19, hiệu năng code được tạo ra cũng được cải thiện nhẹ nói chung.

Linker

Trên Linux, linker giờ chọn dynamic interpreter cho glibc hoặc musl tại thời điểm link.

Trên Windows, Go linker giờ hỗ trợ các C toolchain dựa trên LLVM hiện đại.

Go 1.20 dùng tiền tố go:type: cho các ký hiệu được tạo bởi compiler thay vì go.type.. Điều này tránh nhầm lẫn cho các gói người dùng có tên bắt đầu bằng go.. Gói debug/gosym hiểu quy ước đặt tên mới này cho các binary được build với Go 1.20 trở lên.

Bootstrap

Khi build bản phát hành Go từ source và GOROOT_BOOTSTRAP không được đặt, các phiên bản Go trước tìm kiếm bootstrap toolchain Go 1.4 hoặc mới hơn trong thư mục $HOME/go1.4 (%HOMEDRIVE%%HOMEPATH%\go1.4 trên Windows). Go 1.18 và Go 1.19 tìm kiếm $HOME/go1.17 hoặc $HOME/sdk/go1.17 trước trước khi dùng $HOME/go1.4, để chuẩn bị cho việc yêu cầu Go 1.17 khi bootstrap Go 1.20. Go 1.20 thực sự yêu cầu bản phát hành Go 1.17 để bootstrap, nhưng chúng tôi nhận ra nên dùng điểm phát hành mới nhất của bootstrap toolchain, vì vậy nó yêu cầu Go 1.17.13. Go 1.20 tìm kiếm $HOME/go1.17.13 hoặc $HOME/sdk/go1.17.13 trước khi dùng $HOME/go1.4 (để hỗ trợ các hệ thống đã hard-code đường dẫn $HOME/go1.4 nhưng đã cài đặt Go toolchain mới hơn ở đó). Trong tương lai, chúng tôi có kế hoạch cập nhật bootstrap toolchain mỗi năm một lần, và đặc biệt chúng tôi kỳ vọng Go 1.22 sẽ yêu cầu điểm phát hành cuối cùng của Go 1.20 để bootstrap.

Thư viện chuẩn

Gói crypto/ecdh mới

Go 1.20 thêm gói crypto/ecdh mới để cung cấp hỗ trợ tường minh cho trao đổi khóa Elliptic Curve Diffie-Hellman qua các đường cong NIST và Curve25519.

Các chương trình nên dùng crypto/ecdh thay vì chức năng cấp thấp hơn trong crypto/elliptic cho ECDH, và các module bên thứ ba cho các trường hợp sử dụng nâng cao hơn.

Bọc nhiều lỗi

Go 1.20 mở rộng hỗ trợ bọc lỗi để cho phép một lỗi bọc nhiều lỗi khác.

Một lỗi e có thể bọc nhiều hơn một lỗi bằng cách cung cấp phương thức Unwrap trả về []error.

Các hàm errors.Iserrors.As đã được cập nhật để kiểm tra các lỗi được bọc nhiều lần.

Hàm fmt.Errorf giờ hỗ trợ nhiều lần xuất hiện của động từ định dạng %w, sẽ khiến nó trả về một lỗi bọc tất cả các toán hạng lỗi đó.

Hàm mới errors.Join trả về một lỗi bọc danh sách các lỗi.

HTTP ResponseController

Kiểu "net/http".ResponseController mới cung cấp quyền truy cập vào chức năng mở rộng theo từng yêu cầu không được xử lý bởi interface "net/http".ResponseWriter.

Trước đây, chúng tôi đã thêm chức năng theo từng yêu cầu mới bằng cách định nghĩa các interface tùy chọn mà ResponseWriter có thể triển khai, chẳng hạn như Flusher. Các interface này không thể khám phá và cồng kềnh khi sử dụng.

Kiểu ResponseController cung cấp cách thêm điều khiển theo handler rõ ràng hơn, dễ khám phá hơn. Hai điều khiển như vậy cũng được thêm trong Go 1.20 là SetReadDeadlineSetWriteDeadline, cho phép đặt deadline đọc và ghi theo từng yêu cầu. Ví dụ:

func RequestHandler(w ResponseWriter, r *Request) {
  rc := http.NewResponseController(w)
  rc.SetWriteDeadline(time.Time{}) // vô hiệu hóa Server.WriteTimeout khi gửi response lớn
  io.Copy(w, bigData)
}

Hook Rewrite mới cho ReverseProxy

Proxy chuyển tiếp httputil.ReverseProxy bao gồm hàm hook Rewrite mới, thay thế hook Director trước đây.

Hook Rewrite nhận tham số ProxyRequest, bao gồm cả yêu cầu đến nhận bởi proxy và yêu cầu đi mà nó sẽ gửi. Khác với hook Director, chỉ hoạt động trên yêu cầu đi, điều này cho phép hook Rewrite tránh một số tình huống nhất định khi yêu cầu đến độc hại có thể khiến header được thêm bởi hook bị xóa trước khi chuyển tiếp. Xem issue #50580.

Phương thức ProxyRequest.SetURL định tuyến yêu cầu đi đến đích đã cung cấp và thay thế hàm NewSingleHostReverseProxy. Khác với NewSingleHostReverseProxy, SetURL cũng đặt header Host của yêu cầu đi.

Phương thức ProxyRequest.SetXForwarded đặt các header X-Forwarded-For, X-Forwarded-Host, và X-Forwarded-Proto của yêu cầu đi. Khi dùng Rewrite, các header này không được thêm theo mặc định.

Ví dụ về hook Rewrite sử dụng các tính năng này là:

proxyHandler := &httputil.ReverseProxy{
  Rewrite: func(r *httputil.ProxyRequest) {
    r.SetURL(outboundURL) // Chuyển tiếp yêu cầu đến outboundURL.
    r.SetXForwarded()     // Đặt các header X-Forwarded-*.
    r.Out.Header.Set("X-Additional-Header", "header được đặt bởi proxy")
  },
}

ReverseProxy không còn thêm header User-Agent vào các yêu cầu được chuyển tiếp khi yêu cầu đến không có header đó.

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

Khi biến môi trường GODEBUG=tarinsecurepath=0 được đặt, phương thức Reader.Next giờ sẽ trả về lỗi ErrInsecurePath cho một mục có tên tệp là đường dẫn tuyệt đối, tham chiếu đến vị trí ngoài thư mục hiện tại, chứa ký tự không hợp lệ, hoặc (trên Windows) là tên dành riêng như NUL. Phiên bản Go tương lai có thể tắt đường dẫn không an toàn theo mặc định.

archive/zip

Khi biến môi trường GODEBUG=zipinsecurepath=0 được đặt, NewReader giờ sẽ trả về lỗi ErrInsecurePath khi mở một archive chứa bất kỳ tên tệp nào là đường dẫn tuyệt đối, tham chiếu đến vị trí ngoài thư mục hiện tại, chứa ký tự không hợp lệ, hoặc (trên Windows) là tên dành riêng như NUL. Phiên bản Go tương lai có thể tắt đường dẫn không an toàn theo mặc định.

Đọc từ tệp thư mục có chứa dữ liệu tệp giờ sẽ trả về lỗi. Đặc tả zip không cho phép tệp thư mục chứa dữ liệu tệp, vì vậy thay đổi này chỉ ảnh hưởng khi đọc từ các archive không hợp lệ.

bytes

Các hàm mới CutPrefixCutSuffix giống như TrimPrefixTrimSuffix nhưng cũng báo cáo liệu string có được cắt hay không.

Hàm mới Clone cấp phát bản sao của một byte slice.

context

Hàm mới WithCancelCause cung cấp cách hủy một context với lỗi đã cho. Lỗi đó có thể lấy lại bằng cách gọi hàm mới Cause.

crypto/ecdsa

Khi sử dụng các đường cong được hỗ trợ, tất cả phép tính giờ được triển khai trong thời gian không đổi. Điều này dẫn đến tăng thời gian CPU từ 5% đến 30%, chủ yếu ảnh hưởng đến P-384 và P-521.

Phương thức mới PrivateKey.ECDH chuyển đổi ecdsa.PrivateKey sang ecdh.PrivateKey.

crypto/ed25519

Phương thức PrivateKey.Sign và hàm VerifyWithOptions giờ hỗ trợ ký các thông điệp được băm trước với Ed25519ph, được chỉ định bởi Options.HashFunc trả về crypto.SHA512. Chúng cũng hỗ trợ Ed25519ctx và Ed25519ph với context, được chỉ định bằng cách đặt trường Options.Context mới.

crypto/rsa

Trường mới OAEPOptions.MGFHash cho phép cấu hình MGF1 hash riêng biệt cho OAEP decryption.

crypto/rsa giờ sử dụng backend mới, an toàn hơn, với thời gian không đổi. Điều này gây ra tăng thời gian CPU cho các phép giải mã từ khoảng 15% (RSA-2048 trên amd64) đến 45% (RSA-4096 trên arm64), và nhiều hơn trên kiến trúc 32-bit. Các phép mã hóa chậm hơn khoảng 20 lần so với trước (nhưng vẫn nhanh hơn 5-10 lần so với giải mã). Hiệu năng dự kiến sẽ cải thiện trong các bản phát hành tương lai. Các chương trình không được sửa đổi hoặc tạo thủ công các trường của PrecomputedValues.

crypto/subtle

Hàm mới XORBytes XOR hai byte slice với nhau.

crypto/tls

Các chứng chỉ đã phân tích giờ được chia sẻ giữa tất cả các client đang tích cực sử dụng chứng chỉ đó. Tiết kiệm bộ nhớ có thể đáng kể trong các chương trình thực hiện nhiều kết nối đồng thời đến một máy chủ hoặc tập hợp máy chủ chia sẻ bất kỳ phần nào của chuỗi chứng chỉ của họ.

Khi handshake thất bại do lỗi xác minh chứng chỉ, TLS client và server giờ trả về lỗi kiểu mới CertificateVerificationError, bao gồm các chứng chỉ được trình bày.

crypto/x509

ParsePKCS8PrivateKeyMarshalPKCS8PrivateKey giờ hỗ trợ khóa kiểu *crypto/ecdh.PrivateKey. ParsePKIXPublicKeyMarshalPKIXPublicKey giờ hỗ trợ khóa kiểu *crypto/ecdh.PublicKey. Phân tích khóa đường cong NIST vẫn trả về giá trị kiểu *ecdsa.PublicKey*ecdsa.PrivateKey. Dùng các phương thức ECDH mới của chúng để chuyển đổi sang kiểu crypto/ecdh.

Hàm mới SetFallbackRoots cho phép chương trình định nghĩa một tập chứng chỉ root dự phòng trong trường hợp trình xác minh hệ điều hành hoặc gói root nền tảng chuẩn không có sẵn khi chạy. Nó thường được dùng nhiều nhất với một gói mới, golang.org/x/crypto/x509roots/fallback, sẽ cung cấp gói root được cập nhật.

debug/elf

Các lần thử đọc từ phần SHT_NOBITS bằng cách dùng Section.Data hoặc reader được trả bởi Section.Open giờ trả về lỗi.

Các hằng số R_LARCH_* bổ sung được định nghĩa để dùng với hệ thống LoongArch.

Các hằng số R_PPC64_* bổ sung được định nghĩa để dùng với các relocation PPC64 ELFv2.

Giá trị hằng số cho R_PPC64_SECTOFF_LO_DS được sửa, từ 61 thành 62.

debug/gosym

Do thay đổi quy ước đặt tên ký hiệu của Go, các công cụ xử lý Go binary nên dùng gói debug/gosym của Go 1.20 để xử lý cả binary cũ và mới một cách trong suốt.

debug/pe

Các hằng số IMAGE_FILE_MACHINE_RISCV* bổ sung được định nghĩa để dùng với hệ thống RISC-V.

encoding/binary

Các hàm ReadVarintReadUvarint giờ trả về io.ErrUnexpectedEOF sau khi đọc giá trị một phần, thay vì io.EOF.

encoding/xml

Phương thức mới Encoder.Close có thể dùng để kiểm tra các phần tử chưa đóng khi kết thúc encoding.

Decoder giờ từ chối các tên phần tử và thuộc tính có nhiều hơn một dấu hai chấm, chẳng hạn <a:b:c>, cũng như namespace phân giải thành chuỗi rỗng, chẳng hạn xmlns:a="".

Decoder giờ từ chối các phần tử sử dụng tiền tố namespace khác nhau trong thẻ mở và đóng, ngay cả khi cả hai tiền tố đó đều ký hiệu cùng một namespace.

errors

Hàm mới Join trả về một lỗi bọc danh sách các lỗi.

fmt

Hàm Errorf hỗ trợ nhiều lần xuất hiện của động từ định dạng %w, trả về một lỗi có thể unwrap thành danh sách tất cả đối số cho %w.

Hàm mới FormatString khôi phục directive định dạng tương ứng với State, có thể hữu ích trong các triển khai Formatter.

go/ast

Trường mới RangeStmt.Range ghi lại vị trí của từ khóa range trong câu lệnh range.

Các trường mới File.FileStartFile.FileEnd ghi lại vị trí bắt đầu và kết thúc của toàn bộ tệp source.

go/token

Phương thức mới FileSet.RemoveFile xóa một tệp khỏi FileSet. Các chương trình chạy dài có thể dùng điều này để giải phóng bộ nhớ liên quan đến các tệp không còn cần.

go/types

Hàm mới Satisfies báo cáo liệu một kiểu có thỏa mãn một ràng buộc hay không. Thay đổi này phù hợp với ngữ nghĩa ngôn ngữ mới phân biệt việc thỏa mãn một ràng buộc với việc triển khai một interface.

html/template

Go 1.20.3 trở lên không cho phép các action trong template literal ECMAScript 6. Hành vi này có thể hoàn nguyên bằng cài đặt GODEBUG=jstmpllitinterp=1.

io

OffsetWriter mới bọc WriterAt bên dưới và cung cấp các phương thức Seek, Write, và WriteAt điều chỉnh vị trí offset tệp hiệu quả của chúng bởi một lượng cố định.

io/fs

Lỗi mới SkipAll kết thúc một WalkDir ngay lập tức nhưng thành công.

math/big

Phạm vi rộng và thời gian phụ thuộc đầu vào của gói math/big khiến nó không phù hợp để triển khai mật mã học. Các gói mật mã học trong thư viện chuẩn không còn gọi các phương thức Int không tầm thường trên các đầu vào do kẻ tấn công kiểm soát. Trong tương lai, việc xác định xem một lỗi trong math/big có được coi là lỗ hổng bảo mật hay không sẽ phụ thuộc vào tác động rộng hơn của nó đối với thư viện chuẩn.

math/rand

Gói math/rand giờ tự động seed bộ tạo số ngẫu nhiên toàn cục (được dùng bởi các hàm cấp cao nhất như Float64Int) với một giá trị ngẫu nhiên, và hàm Seed cấp cao nhất đã bị deprecated. Các chương trình cần chuỗi số ngẫu nhiên có thể tái tạo nên ưu tiên cấp phát nguồn ngẫu nhiên riêng, dùng rand.New(rand.NewSource(seed)).

Các chương trình cần hành vi seed toàn cục nhất quán trước đó có thể đặt GODEBUG=randautoseed=0 trong môi trường của chúng.

Hàm Read cấp cao nhất đã bị deprecated. Trong hầu hết các trường hợp, crypto/rand.Read phù hợp hơn.

mime

Hàm ParseMediaType giờ cho phép tên tham số trùng lặp, miễn là giá trị của các tên đó giống nhau.

mime/multipart

Các phương thức của kiểu Reader giờ bọc các lỗi được trả bởi io.Reader bên dưới.

Trong Go 1.19.8 trở lên, gói này giới hạn kích thước dữ liệu MIME mà nó xử lý để bảo vệ trước các đầu vào độc hại. Reader.NextPartReader.NextRawPart giới hạn số header trong một phần ở 10000 và Reader.ReadForm giới hạn tổng số header trong tất cả FileHeaders ở 10000. Các giới hạn này có thể điều chỉnh với cài đặt GODEBUG=multipartmaxheaders. Reader.ReadForm tiếp tục giới hạn số phần trong form ở 1000. Giới hạn này có thể điều chỉnh với cài đặt GODEBUG=multipartmaxparts.

net

Hàm LookupCNAME giờ trả về nội dung của bản ghi CNAME một cách nhất quán khi có một bản ghi. Trước đây trên hệ thống Unix và khi dùng pure Go resolver, LookupCNAME sẽ trả về lỗi nếu bản ghi CNAME tham chiếu đến tên không có bản ghi A, AAAA, hoặc CNAME. Thay đổi này sửa LookupCNAME để khớp với hành vi trước đó trên Windows, cho phép LookupCNAME thành công bất cứ khi nào CNAME tồn tại.

Interface.Flags giờ bao gồm cờ mới FlagRunning, cho biết một interface đang hoạt động. Một interface được cấu hình về mặt quản trị nhưng không hoạt động (ví dụ: cáp mạng chưa kết nối) sẽ có FlagUp được đặt nhưng không có FlagRunning.

Trường mới Dialer.ControlContext chứa hàm callback tương tự hook Dialer.Control hiện có, nhưng bổ sung chấp nhận context của dial làm tham số. Control bị bỏ qua khi ControlContext khác nil.

DNS resolver của Go nhận ra tùy chọn resolver trust-ad. Khi options trust-ad được đặt trong resolv.conf, Go resolver sẽ đặt bit AD trong các truy vấn DNS. Resolver không sử dụng bit AD trong các phản hồi.

Phân giải DNS sẽ phát hiện các thay đổi đối với /etc/nsswitch.conf và tải lại tệp khi nó thay đổi. Các kiểm tra được thực hiện nhiều nhất mỗi năm giây, khớp với cách xử lý trước đó của /etc/hosts/etc/resolv.conf.

net/http

Hàm ResponseWriter.WriteHeader giờ hỗ trợ gửi mã trạng thái 1xx.

Cài đặt cấu hình mới Server.DisableGeneralOptionsHandler cho phép tắt handler OPTIONS * mặc định.

Hook mới Transport.OnProxyConnectResponse được gọi khi Transport nhận phản hồi HTTP từ proxy cho yêu cầu CONNECT.

HTTP server giờ chấp nhận các yêu cầu HEAD có chứa body, thay vì từ chối chúng như không hợp lệ.

Lỗi stream HTTP/2 được trả bởi các hàm net/http có thể được chuyển đổi thành golang.org/x/net/http2.StreamError bằng cách dùng errors.As.

Các khoảng trắng ở đầu và cuối được cắt khỏi tên cookie, thay vì bị từ chối như không hợp lệ. Ví dụ: cài đặt cookie “name =value” giờ được chấp nhận là đặt cookie “name”.

Một Cookie có trường Expires rỗng giờ được coi là hợp lệ. Cookie.Valid chỉ kiểm tra Expires khi nó được đặt.

net/netip

Các hàm mới IPv6LinkLocalAllRoutersIPv6Loopback là các tương đương net/netip của net.IPv6loopbacknet.IPv6linklocalallrouters.

os

Trên Windows, tên NUL không còn được xử lý như trường hợp đặc biệt trong MkdirStat.

Trên Windows, File.Stat giờ dùng file handle để lấy các thuộc tính khi tệp là thư mục. Trước đây nó sẽ dùng đường dẫn được truyền cho Open, vốn có thể không còn là tệp được đại diện bởi file handle nếu tệp đã bị di chuyển hoặc thay thế. Thay đổi này sửa Open để mở thư mục mà không có quyền truy cập FILE_SHARE_DELETE, khớp với hành vi của các tệp thông thường.

Trên Windows, File.Seek giờ hỗ trợ seek đến đầu thư mục.

os/exec

Các trường mới Cmd CancelWaitDelay chỉ định hành vi của Cmd khi Context liên kết của nó bị hủy hoặc quá trình của nó thoát với các I/O pipe vẫn được giữ mở bởi một tiến trình con.

path/filepath

Lỗi mới SkipAll kết thúc một Walk ngay lập tức nhưng thành công.

Hàm mới IsLocal báo cáo liệu một đường dẫn có cục bộ về mặt từ vựng với một thư mục hay không. Ví dụ: nếu IsLocal(p)true, thì Open(p) sẽ tham chiếu đến một tệp nằm về mặt từ vựng trong cây con có gốc tại thư mục hiện tại.

reflect

Các phương thức mới Value.ComparableValue.Equal có thể dùng để so sánh hai Value về tính bằng nhau. Comparable báo cáo liệu Equal có phải là phép tính hợp lệ cho một receiver Value đã cho hay không.

Phương thức mới Value.Grow mở rộng một slice để đảm bảo chỗ cho thêm n phần tử.

Phương thức mới Value.SetZero đặt một giá trị thành giá trị zero cho kiểu của nó.

Go 1.18 đã giới thiệu các phương thức Value.SetIterKeyValue.SetIterValue. Đây là các tối ưu hóa: v.SetIterKey(it) được thiết kế tương đương với v.Set(it.Key()). Các triển khai không đúng cách đã bỏ qua kiểm tra việc sử dụng các trường không được export có trong các dạng không tối ưu. Go 1.20 sửa các phương thức này để bao gồm kiểm tra trường không được export.

regexp

Go 1.19.2 và Go 1.18.7 bao gồm bản sửa lỗi bảo mật cho parser biểu thức chính quy, làm nó từ chối các biểu thức rất lớn tiêu thụ quá nhiều bộ nhớ. Vì các bản Go patch không giới thiệu API mới, parser trả về syntax.ErrInternalError trong trường hợp này. Go 1.20 thêm lỗi cụ thể hơn, syntax.ErrLarge, mà parser giờ trả về thay thế.

runtime/cgo

Go 1.20 thêm kiểu marker Incomplete mới. Code được tạo bởi cgo sẽ dùng cgo.Incomplete để đánh dấu kiểu C không đầy đủ.

runtime/metrics

Go 1.20 thêm các metric được hỗ trợ mới, bao gồm cài đặt GOMAXPROCS hiện tại (/sched/gomaxprocs:threads), số lời gọi cgo được thực thi (/cgo/go-to-c-calls:calls), tổng thời gian chặn mutex (/sync/mutex/wait/total:seconds), và nhiều số liệu đo thời gian dành cho bộ gom rác.

Các metric histogram dựa trên thời gian giờ kém chính xác hơn, nhưng chiếm ít bộ nhớ hơn nhiều.

runtime/pprof

Các mẫu mutex profile giờ được tính trước, sửa vấn đề khi các mẫu mutex profile cũ sẽ bị tính sai nếu tỷ lệ lấy mẫu thay đổi trong quá trình thực thi.

Các profile được thu thập trên Windows giờ bao gồm thông tin ánh xạ bộ nhớ để sửa các vấn đề symbolization cho các binary position-independent.

runtime/trace

Background sweeper của bộ gom rác giờ yield ít thường xuyên hơn, dẫn đến ít sự kiện thừa hơn nhiều trong các execution trace.

strings

Các hàm mới CutPrefixCutSuffix giống như TrimPrefixTrimSuffix nhưng cũng báo cáo liệu string có được cắt hay không.

sync

Các phương thức Map mới Swap, CompareAndSwap, và CompareAndDelete cho phép cập nhật các mục map hiện có một cách nguyên tử.

syscall

Trên FreeBSD, các shim tương thích cần cho FreeBSD 11 và cũ hơn đã bị xóa.

Trên Linux, các hằng số CLONE_* bổ sung được định nghĩa để dùng với trường SysProcAttr.Cloneflags.

Trên Linux, các trường SysProcAttr.CgroupFD mới và SysProcAttr.UseCgroupFD cung cấp cách đặt tiến trình con vào một cgroup cụ thể.

testing

Phương thức mới B.Elapsed báo cáo thời gian đã trôi qua hiện tại của benchmark, có thể hữu ích để tính tốc độ để báo cáo với ReportMetric.

Gọi T.Run từ một hàm được truyền cho T.Cleanup chưa bao giờ được định nghĩa rõ ràng, và giờ sẽ panic.

time

Các hằng số layout thời gian mới DateTime, DateOnly, và TimeOnly cung cấp tên cho ba trong số các chuỗi layout phổ biến nhất được dùng trong cuộc khảo sát code Go công khai.

Phương thức mới Time.Compare so sánh hai thời điểm.

Parse giờ bỏ qua độ chính xác dưới nano giây trong đầu vào của nó, thay vì báo cáo các chữ số đó như lỗi.

Phương thức Time.MarshalJSON giờ nghiêm ngặt hơn về việc tuân thủ RFC 3339.

unicode/utf16

Hàm mới AppendRune nối encoding UTF-16 của một rune đã cho vào slice uint16, tương tự như utf8.AppendRune.