Ghi chú phát hành Go 1.18

Giới thiệu về Go 1.18

Bản phát hành Go mới nhất, phiên bản 1.18, là một bản phát hành quan trọng, bao gồm các thay đổi về ngôn ngữ, triển khai toolchain, runtime và thư viện. Go 1.18 ra đời bảy tháng sau Go 1.17. Như thường lệ, bản phát hành này duy trì cam kết tương thích của Go 1. Chúng tôi kỳ vọng hầu hết các chương trình Go sẽ tiếp tục biên dịch và chạy như trước đây.

Thay đổi về ngôn ngữ

Generics

Go 1.18 bao gồm một triển khai các tính năng generics như được mô tả trong Đề xuất Type Parameters. Điều này bao gồm các thay đổi lớn nhưng hoàn toàn tương thích ngược đối với ngôn ngữ.

Những thay đổi ngôn ngữ mới này đòi hỏi một lượng lớn code mới chưa được kiểm tra đáng kể trong môi trường sản xuất. Điều đó sẽ chỉ xảy ra khi ngày càng nhiều người viết và sử dụng code generic. Chúng tôi tin rằng tính năng này được triển khai tốt và chất lượng cao. Tuy nhiên, không như hầu hết các khía cạnh của Go, chúng tôi không thể hỗ trợ niềm tin đó bằng kinh nghiệm thực tế. Do đó, trong khi chúng tôi khuyến khích việc sử dụng generics khi phù hợp, hãy thận trọng khi triển khai code generic trong môi trường sản xuất.

Mặc dù chúng tôi tin rằng các tính năng ngôn ngữ mới được thiết kế tốt và được đặc tả rõ ràng, có thể chúng tôi đã mắc lỗi. Chúng tôi muốn nhấn mạnh rằng cam kết tương thích Go 1 ghi rằng “Nếu cần thiết phải giải quyết sự không nhất quán hoặc không hoàn chỉnh trong đặc tả, việc giải quyết vấn đề có thể ảnh hưởng đến ý nghĩa hoặc tính hợp lệ của các chương trình hiện có. Chúng tôi bảo lưu quyền giải quyết các vấn đề như vậy, bao gồm cập nhật các triển khai.” Nó cũng nói rằng “Nếu trình biên dịch hoặc thư viện có lỗi vi phạm đặc tả, một chương trình phụ thuộc vào hành vi lỗi đó có thể bị hỏng nếu lỗi được sửa. Chúng tôi bảo lưu quyền sửa các lỗi như vậy.” Nói cách khác, có thể sẽ có code sử dụng generics hoạt động được với bản phát hành 1.18 nhưng bị hỏng trong các bản phát hành sau. Chúng tôi không có kế hoạch hoặc kỳ vọng thực hiện bất kỳ thay đổi như vậy. Tuy nhiên, việc phá vỡ các chương trình 1.18 trong các bản phát hành tương lai có thể trở nên cần thiết vì những lý do chúng tôi hiện không thể lường trước. Chúng tôi sẽ giảm thiểu bất kỳ sự phá vỡ như vậy càng nhiều càng tốt, nhưng chúng tôi không thể đảm bảo rằng sự phá vỡ sẽ bằng không.

Sau đây là danh sách các thay đổi nổi bật nhất. Để có cái nhìn tổng quan đầy đủ hơn, xem đề xuất. Để biết chi tiết, xem đặc tả ngôn ngữ.

  • Cú pháp cho các khai báo hàmkiểu hiện chấp nhận các tham số kiểu.
  • Các hàm và kiểu được tham số hóa có thể được khởi tạo bằng cách theo sau chúng với danh sách các đối số kiểu trong dấu ngoặc vuông.
  • Token mới ~ đã được thêm vào tập hợp các toán tử và dấu câu.
  • Cú pháp cho các kiểu Interface hiện cho phép nhúng các kiểu tùy ý (không chỉ tên kiểu của các interface) cũng như các phần tử kiểu union và ~T. Các interface như vậy chỉ có thể được sử dụng làm ràng buộc kiểu. Một interface hiện định nghĩa một tập hợp các kiểu cũng như một tập hợp các phương thức.
  • Định danh được khai báo trước mới any là bí danh cho interface rỗng. Nó có thể được sử dụng thay vì interface{}.
  • Định danh được khai báo trước mới comparable là một interface biểu thị tập hợp tất cả các kiểu có thể được so sánh bằng == hoặc !=. Nó chỉ có thể được sử dụng như là (hoặc được nhúng trong) một ràng buộc kiểu.

Có ba package thử nghiệm sử dụng generics có thể hữu ích. Các package này nằm trong kho x/exp; API của chúng không được bao phủ bởi cam kết Go 1 và có thể thay đổi khi chúng tôi có thêm kinh nghiệm với generics.

golang.org/x/exp/constraints

Các ràng buộc hữu ích cho code generic, chẳng hạn như constraints.Ordered.

golang.org/x/exp/slices

Tập hợp các hàm generic hoạt động trên các slice của bất kỳ kiểu phần tử nào.

golang.org/x/exp/maps

Tập hợp các hàm generic hoạt động trên các map với bất kỳ kiểu key hoặc kiểu phần tử nào.

Triển khai generics hiện tại có các giới hạn đã biết sau:

  • Trình biên dịch Go không thể xử lý các khai báo kiểu bên trong các hàm hoặc phương thức generic. Chúng tôi hy vọng cung cấp hỗ trợ cho tính năng này trong một bản phát hành trong tương lai.
  • Trình biên dịch Go không chấp nhận các đối số có kiểu tham số kiểu với các hàm được khai báo trước real, imagcomplex. Chúng tôi hy vọng loại bỏ hạn chế này trong một bản phát hành trong tương lai.
  • Trình biên dịch Go chỉ hỗ trợ gọi phương thức m trên giá trị x của kiểu tham số kiểu P nếu m được khai báo tường minh bởi interface ràng buộc của P. Tương tự, các giá trị phương thức x.m và các biểu thức phương thức P.m cũng chỉ được hỗ trợ nếu m được khai báo tường minh bởi P, mặc dù m có thể nằm trong tập phương thức của P do tất cả các kiểu trong P đều triển khai m. Chúng tôi hy vọng loại bỏ hạn chế này trong một bản phát hành trong tương lai.
  • Trình biên dịch Go không hỗ trợ truy cập trường struct x.f khi x có kiểu tham số kiểu ngay cả khi tất cả các kiểu trong tập kiểu của tham số kiểu có trường f. Chúng tôi có thể loại bỏ hạn chế này trong một bản phát hành trong tương lai.
  • Việc nhúng một tham số kiểu, hoặc con trỏ đến tham số kiểu, như là một trường không tên trong kiểu struct là không được phép. Tương tự, việc nhúng tham số kiểu trong kiểu interface là không được phép. Hiện tại chưa rõ liệu những điều này có bao giờ được cho phép hay không.
  • Một phần tử union với nhiều hơn một term có thể không chứa kiểu interface với tập phương thức không rỗng. Hiện tại chưa rõ liệu điều này có bao giờ được cho phép hay không.

Generics cũng đại diện cho một thay đổi lớn đối với hệ sinh thái Go. Mặc dù chúng tôi đã cập nhật một số công cụ cốt lõi với hỗ trợ generics, vẫn còn nhiều việc phải làm. Sẽ cần thời gian để các công cụ, tài liệu và thư viện còn lại theo kịp những thay đổi ngôn ngữ này.

Sửa lỗi

Trình biên dịch Go 1.18 hiện báo cáo đúng các lỗi declared but not used cho các biến được đặt bên trong một function literal nhưng không bao giờ được sử dụng. Trước Go 1.18, trình biên dịch không báo lỗi trong các trường hợp như vậy. Điều này sửa lỗi trình biên dịch tồn tại lâu dài #8560. Do thay đổi này, các chương trình (có thể không đúng) có thể không biên dịch được nữa. Cách sửa cần thiết rất đơn giản: sửa chương trình nếu thực sự nó không đúng, hoặc sử dụng biến vi phạm, ví dụ bằng cách gán nó cho định danh trống _. Vì go vet luôn chỉ ra lỗi này, số lượng chương trình bị ảnh hưởng có thể rất nhỏ.

Trình biên dịch Go 1.18 hiện báo cáo tràn số khi truyền một biểu thức hằng rune như '1' << 32 làm đối số cho các hàm được khai báo trước printprintln, nhất quán với hành vi của các hàm do người dùng định nghĩa. Trước Go 1.18, trình biên dịch không báo lỗi trong các trường hợp như vậy nhưng chấp nhận im lặng các đối số hằng như vậy nếu chúng vừa trong int64. Do thay đổi này, các chương trình (có thể không đúng) có thể không biên dịch được nữa. Cách sửa cần thiết rất đơn giản: sửa chương trình nếu thực sự nó không đúng, hoặc chuyển đổi tường minh đối số vi phạm sang kiểu đúng. Vì go vet luôn chỉ ra lỗi này, số lượng chương trình bị ảnh hưởng có thể rất nhỏ.

Các nền tảng

AMD64

Go 1.18 giới thiệu biến môi trường GOAMD64 mới, chọn tại thời điểm biên dịch phiên bản mục tiêu tối thiểu của kiến trúc AMD64. Các giá trị được phép là v1, v2, v3 hoặc v4. Mỗi cấp độ cao hơn yêu cầu và tận dụng các tính năng bộ xử lý bổ sung. Mô tả chi tiết có thể tìm thấy tại đây.

Biến môi trường GOAMD64 mặc định là v1.

RISC-V

Kiến trúc RISC-V 64-bit trên Linux (cổng linux/riscv64) hiện hỗ trợ các chế độ build c-archivec-shared.

Linux

Go 1.18 yêu cầu Linux kernel phiên bản 2.6.32 trở lên.

Windows

Các cổng windows/armwindows/arm64 hiện hỗ trợ preemption không cộng tác, đưa khả năng này đến tất cả bốn cổng Windows, điều này hy vọng sẽ giải quyết các lỗi khó phát hiện khi gọi vào các hàm Win32 bị chặn trong thời gian dài.

iOS

Trên iOS (cổng ios/arm64) và trình giả lập iOS chạy trên macOS dựa trên AMD64 (cổng ios/amd64), Go 1.18 hiện yêu cầu iOS 12 trở lên; hỗ trợ cho các phiên bản trước đã bị ngừng.

FreeBSD

Go 1.18 là bản phát hành cuối cùng được hỗ trợ trên FreeBSD 11.x, vốn đã đạt đến ngày kết thúc vòng đời. Go 1.19 sẽ yêu cầu FreeBSD 12.2+ hoặc FreeBSD 13.0+. FreeBSD 13.0+ sẽ yêu cầu một kernel với tùy chọn COMPAT_FREEBSD12 được đặt (đây là mặc định).

Công cụ

Fuzzing

Go 1.18 bao gồm một triển khai fuzzing như được mô tả trong đề xuất fuzzing.

Xem trang landing fuzzing để bắt đầu.

Hãy lưu ý rằng fuzzing có thể tiêu thụ nhiều bộ nhớ và có thể ảnh hưởng đến hiệu suất máy của bạn trong khi chạy. Cũng lưu ý rằng engine fuzzing ghi các giá trị mở rộng phủ sóng test vào thư mục fuzz cache trong $GOCACHE/fuzz trong khi chạy. Hiện tại không có giới hạn về số file hoặc tổng số byte có thể được ghi vào fuzz cache, vì vậy nó có thể chiếm nhiều dung lượng lưu trữ (có thể vài GB).

Lệnh go

go get

go get không còn build hoặc cài đặt các package trong chế độ nhận biết module. go get hiện dành riêng cho việc điều chỉnh các dependency trong go.mod. Thực tế là cờ -d luôn được bật. Để cài đặt phiên bản mới nhất của một tệp thực thi ngoài ngữ cảnh của module hiện tại, hãy sử dụng go install example.com/cmd@latest. Bất kỳ truy vấn phiên bản nào có thể được sử dụng thay vì latest. Dạng go install này đã được thêm vào trong Go 1.16, vì vậy các dự án hỗ trợ các phiên bản cũ hơn có thể cần cung cấp hướng dẫn cài đặt cho cả go install lẫn go get. go get hiện báo lỗi khi được sử dụng ngoài một module, vì không có file go.mod để cập nhật. Trong chế độ GOPATH (với GO111MODULE=off), go get vẫn build và cài đặt các package như trước.

Cập nhật tự động go.modgo.sum

Các lệnh con go mod graph, go mod vendor, go mod verifygo mod why không còn tự động cập nhật các file go.modgo.sum nữa. (Các file đó có thể được cập nhật tường minh bằng go get, go mod tidy hoặc go mod download.)

go version

Lệnh go hiện nhúng thông tin kiểm soát phiên bản vào các nhị phân. Nó bao gồm revision hiện đang được checkout, thời gian commit và một cờ chỉ ra liệu có các file đã chỉnh sửa hoặc chưa được theo dõi hay không. Thông tin kiểm soát phiên bản được nhúng nếu lệnh go được gọi trong một thư mục trong kho lưu trữ Git, Mercurial, Fossil hoặc Bazaar, và package main cùng module main chứa nó nằm trong cùng kho lưu trữ. Thông tin này có thể bị bỏ qua bằng cờ -buildvcs=false.

Ngoài ra, lệnh go nhúng thông tin về build, bao gồm các build tag và tool tag (được đặt với -tags), trình biên dịch, assembler và các cờ linker (như -gcflags), liệu cgo có được bật không, và nếu có, các giá trị của các biến môi trường cgo (như CGO_CFLAGS). Cả thông tin VCS và build có thể được đọc cùng với thông tin module bằng cách sử dụng go version -m file hoặc runtime/debug.ReadBuildInfo (cho nhị phân đang chạy hiện tại) hoặc package debug/buildinfo mới.

Định dạng dữ liệu cơ bản của thông tin build được nhúng có thể thay đổi với các bản phát hành Go mới, vì vậy một phiên bản go cũ hơn có thể không xử lý được thông tin build được tạo ra với phiên bản go mới hơn. Để đọc thông tin phiên bản từ nhị phân được build với go 1.18, hãy sử dụng lệnh go version và package debug/buildinfo từ go 1.18+.

go mod download

Nếu file go.mod của module chính chỉ định go 1.17 hoặc cao hơn, go mod download không có đối số hiện chỉ tải mã nguồn cho các module được yêu cầu tường minh trong file go.mod của module chính. (Trong module go 1.17 hoặc cao hơn, tập hợp đó đã bao gồm tất cả các dependency cần thiết để build các package và test trong module chính.) Để cũng tải mã nguồn cho các dependency bắc cầu, hãy sử dụng go mod download all.

go mod vendor

Lệnh con go mod vendor hiện hỗ trợ cờ -o để đặt thư mục đầu ra. (Các lệnh go khác vẫn đọc từ thư mục vendor tại thư mục gốc module khi tải các package với -mod=vendor, vì vậy việc sử dụng chính của cờ này là cho các công cụ bên thứ ba cần thu thập mã nguồn package.)

go mod tidy

Lệnh go mod tidy hiện giữ lại các checksum bổ sung trong file go.sum cho các module có mã nguồn cần thiết để xác minh rằng mỗi package được import chỉ được cung cấp bởi một module trong danh sách build. Vì điều kiện này hiếm gặp và việc không áp dụng nó dẫn đến lỗi build, thay đổi này không phụ thuộc vào phiên bản go trong file go.mod của module chính.

go work

Lệnh go hiện hỗ trợ chế độ “Workspace”. Nếu một file go.work được tìm thấy trong thư mục làm việc hoặc một thư mục cha, hoặc một file được chỉ định bằng biến môi trường GOWORK, nó sẽ đặt lệnh go vào chế độ workspace. Trong chế độ workspace, file go.work sẽ được sử dụng để xác định tập hợp các module chính được sử dụng làm gốc cho việc giải quyết module, thay vì sử dụng file go.mod thường được tìm thấy để chỉ định module chính duy nhất. Để biết thêm thông tin, xem tài liệu go work.

go build -asan

Lệnh go build và các lệnh liên quan hiện hỗ trợ cờ -asan bật khả năng tương tác với code C (hoặc C++) được biên dịch với address sanitizer (tùy chọn trình biên dịch C -fsanitize=address).

go test

Lệnh go hiện hỗ trợ các tùy chọn dòng lệnh bổ sung cho hỗ trợ fuzzing mới được mô tả ở trên:

  • go test hỗ trợ các tùy chọn -fuzz, -fuzztime-fuzzminimizetime. Để biết tài liệu về những điều này, xem go help testflag.
  • go clean hỗ trợ tùy chọn -fuzzcache. Để biết tài liệu, xem go help clean.

Các dòng //go:build

Go 1.17 đã giới thiệu các dòng //go:build như một cách dễ đọc hơn để viết các ràng buộc build, thay vì các dòng // +build. Kể từ Go 1.17, gofmt thêm các dòng //go:build để khớp với các dòng +build hiện có và giữ chúng đồng bộ, trong khi go vet chẩn đoán khi chúng không đồng bộ.

Vì bản phát hành Go 1.18 đánh dấu kết thúc hỗ trợ cho Go 1.16, tất cả các phiên bản Go được hỗ trợ hiện hiểu các dòng //go:build. Trong Go 1.18, go fix hiện loại bỏ các dòng // +build đã lỗi thời trong các module khai báo go 1.18 hoặc mới hơn trong các file go.mod của chúng.

Để biết thêm thông tin, xem go.dev/design/draft-gobuild.

Gofmt

gofmt hiện đọc và định dạng các file đầu vào đồng thời, với một giới hạn bộ nhớ tỷ lệ với GOMAXPROCS. Trên máy có nhiều CPU, gofmt hiện sẽ nhanh hơn đáng kể.

Vet

Cập nhật cho Generics

Công cụ vet được cập nhật để hỗ trợ code generic. Trong hầu hết các trường hợp, nó báo lỗi trong code generic bất cứ khi nào nó sẽ báo lỗi trong code tương đương không generic sau khi thay thế các tham số kiểu bằng một kiểu từ tập kiểu của chúng. Ví dụ, vet báo lỗi format trong

func Print[T ~int|~string](t T) {
    fmt.Printf("%d", t)
}

vì nó sẽ báo lỗi format trong phiên bản không generic tương đương của Print[string]:

func PrintString(x string) {
    fmt.Printf("%d", x)
}

Cải tiến độ chính xác cho các trình kiểm tra hiện có

Các trình kiểm tra cmd/vet copylock, printf, sortslice, testinggoroutinetests đều có những cải tiến độ chính xác vừa phải để xử lý các mẫu code bổ sung. Điều này có thể dẫn đến các lỗi mới được báo cáo trong các package hiện có. Ví dụ, trình kiểm tra printf hiện theo dõi các chuỗi định dạng được tạo ra bằng cách nối các hằng chuỗi. Vì vậy vet sẽ báo lỗi trong:

  // fmt.Printf formatting directive %d is being passed to Println.
  fmt.Println("%d"+` ≡ x (mod 2)`+"\n", x%2)

Runtime

Bộ gom rác hiện bao gồm các nguồn công việc bộ gom rác không phải heap (ví dụ: quét stack) khi xác định tần suất chạy. Do đó, chi phí bộ gom rác có thể dự đoán hơn khi các nguồn này đáng kể. Đối với hầu hết các ứng dụng, những thay đổi này sẽ không đáng kể; tuy nhiên, một số ứng dụng Go hiện có thể sử dụng ít bộ nhớ hơn và dành nhiều thời gian hơn cho việc gom rác, hoặc ngược lại, so với trước đây. Cách khắc phục dự kiến là điều chỉnh GOGC khi cần thiết.

Runtime hiện trả bộ nhớ về hệ điều hành hiệu quả hơn và đã được điều chỉnh để hoạt động tích cực hơn.

Go 1.17 nhìn chung đã cải thiện định dạng của các đối số trong stack trace, nhưng có thể in các giá trị không chính xác cho các đối số được truyền qua register. Điều này được cải thiện trong Go 1.18 bằng cách in dấu hỏi (?) sau mỗi giá trị có thể không chính xác.

Hàm built-in append hiện sử dụng một công thức hơi khác khi quyết định cần grow slice bao nhiêu khi phải cấp phát mảng nền mới. Công thức mới ít bị đột biến trong hành vi cấp phát hơn.

Trình biên dịch

Go 1.17 đã triển khai một cách mới để truyền các đối số và kết quả hàm bằng register thay vì stack trên kiến trúc x86 64-bit trên các hệ điều hành được chọn. Go 1.18 mở rộng các nền tảng được hỗ trợ để bao gồm ARM 64-bit (GOARCH=arm64), PowerPC 64-bit big-endian và little-endian (GOARCH=ppc64, ppc64le), cũng như kiến trúc x86 64-bit (GOARCH=amd64) trên tất cả các hệ điều hành. Trên các hệ thống ARM 64-bit và PowerPC 64-bit, benchmark cho thấy cải thiện hiệu suất điển hình là 10% hoặc hơn.

Như đã đề cập trong ghi chú phát hành Go 1.17, thay đổi này không ảnh hưởng đến chức năng của bất kỳ code Go an toàn nào và được thiết kế để không tác động đến hầu hết code assembly. Xem ghi chú phát hành Go 1.17 để biết thêm chi tiết.

Trình biên dịch hiện có thể inline các hàm chứa vòng lặp range hoặc vòng lặp for có nhãn.

Tùy chọn trình biên dịch -asan mới hỗ trợ tùy chọn -asan của lệnh go mới.

Vì trình kiểm tra kiểu của trình biên dịch đã được thay thế hoàn toàn để hỗ trợ generics, một số thông báo lỗi hiện có thể dùng từ ngữ khác so với trước đây. Trong một số trường hợp, các thông báo lỗi trước Go 1.18 cung cấp nhiều chi tiết hơn hoặc được diễn đạt theo cách hữu ích hơn. Chúng tôi dự định giải quyết các trường hợp này trong Go 1.19.

Do các thay đổi trong trình biên dịch liên quan đến hỗ trợ generics, tốc độ biên dịch Go 1.18 có thể chậm hơn khoảng 15% so với tốc độ biên dịch Go 1.17. Thời gian thực thi của code đã biên dịch không bị ảnh hưởng. Chúng tôi dự định cải thiện tốc độ của trình biên dịch trong các bản phát hành tương lai.

Linker

Linker phát ra ít relocation hơn nhiều. Do đó, hầu hết các codebase sẽ link nhanh hơn, yêu cầu ít bộ nhớ hơn để link, và tạo ra các nhị phân nhỏ hơn. Các công cụ xử lý nhị phân Go nên sử dụng package debug/gosym của Go 1.18 để xử lý trong suốt cả các nhị phân cũ và mới.

Tùy chọn linker -asan mới hỗ trợ tùy chọn -asan của lệnh go mới.

Bootstrap

Khi build một bản phát hành Go từ nguồn và GOROOT_BOOTSTRAP không được đặt, các phiên bản Go trước đây tìm kiếm toolchain bootstrap Go 1.4 trở lên trong thư mục $HOME/go1.4 (%HOMEDRIVE%%HOMEPATH%\go1.4 trên Windows). Go hiện tìm kiếm đầu tiên cho $HOME/go1.17 hoặc $HOME/sdk/go1.17 trước khi quay trở lại $HOME/go1.4. Chúng tôi dự định Go 1.19 yêu cầu Go 1.17 trở lên để bootstrap, và thay đổi này sẽ làm cho quá trình chuyển đổi mượt mà hơn. Để biết thêm chi tiết, xem go.dev/issue/44505.

Thư viện chuẩn

Package debug/buildinfo mới

Package mới debug/buildinfo cung cấp quyền truy cập vào các phiên bản module, thông tin kiểm soát phiên bản và các cờ build được nhúng vào các file thực thi được build bởi lệnh go. Thông tin tương tự cũng có sẵn thông qua runtime/debug.ReadBuildInfo cho nhị phân đang chạy hiện tại và thông qua go version -m trên dòng lệnh.

Package net/netip mới

Package mới net/netip định nghĩa kiểu địa chỉ IP mới, Addr. So với kiểu net.IP hiện có, kiểu netip.Addr chiếm ít bộ nhớ hơn, bất biến và có thể so sánh nên nó hỗ trợ == và có thể được sử dụng làm key map.

Ngoài Addr, package định nghĩa AddrPort, đại diện cho một IP và port, và Prefix, đại diện cho một prefix CIDR mạng.

Package cũng định nghĩa một số hàm để tạo và kiểm tra các kiểu mới này: AddrFrom4, AddrFrom16, AddrFromSlice, AddrPortFrom, IPv4Unspecified, IPv6LinkLocalAllNodes, IPv6Unspecified, MustParseAddr, MustParseAddrPort, MustParsePrefix, ParseAddr, ParseAddrPort, ParsePrefix, PrefixFrom.

Package net bao gồm các phương thức mới song song với các phương thức hiện có, nhưng trả về netip.AddrPort thay vì kiểu nặng hơn net.IP hoặc *net.UDPAddr: Resolver.LookupNetIP, UDPConn.ReadFromUDPAddrPort, UDPConn.ReadMsgUDPAddrPort, UDPConn.WriteToUDPAddrPort, UDPConn.WriteMsgUDPAddrPort. Các phương thức UDPConn mới hỗ trợ I/O không có cấp phát.

Package net cũng hiện bao gồm các hàm và phương thức để chuyển đổi giữa các kiểu TCPAddr/UDPAddr hiện có và netip.AddrPort: TCPAddrFromAddrPort, UDPAddrFromAddrPort, TCPAddr.AddrPort, UDPAddr.AddrPort.

TLS 1.0 và 1.1 bị tắt mặc định ở phía client

Nếu Config.MinVersion không được đặt, nó hiện mặc định là TLS 1.2 cho các kết nối client. Bất kỳ server cập nhật an toàn nào đều dự kiến hỗ trợ TLS 1.2, và các trình duyệt đã yêu cầu nó kể từ năm 2020. TLS 1.0 và 1.1 vẫn được hỗ trợ bằng cách đặt Config.MinVersion thành VersionTLS10. Giá trị mặc định phía server không thay đổi ở TLS 1.0.

Mặc định có thể tạm thời đặt lại về TLS 1.0 bằng cách đặt biến môi trường GODEBUG=tls10default=1. Tùy chọn này sẽ được xóa trong Go 1.19.

Từ chối chứng chỉ SHA-1

crypto/x509 hiện sẽ từ chối các chứng chỉ được ký bằng hàm băm SHA-1. Điều này không áp dụng cho các chứng chỉ root tự ký. Các cuộc tấn công thực tế chống lại SHA-1 đã được chứng minh kể từ năm 2017 và các Cơ quan chứng nhận được tin cậy công khai đã không cấp chứng chỉ SHA-1 kể từ năm 2015.

Điều này có thể tạm thời đặt lại bằng cách đặt biến môi trường GODEBUG=x509sha1=1. Tùy chọn này sẽ được xóa trong một bản phát hành trong tương lai.

Các thay đổi nhỏ trong thư viện

Như thường lệ, có nhiều thay đổi và cập nhật nhỏ cho thư viện, được thực hiện với cam kết tương thích của Go 1 trong tâm trí.

bufio

Phương thức mới Writer.AvailableBuffer trả về một buffer rỗng với dung lượng có thể không rỗng để sử dụng với các API kiểu append. Sau khi append, buffer có thể được cung cấp cho lời gọi Write tiếp theo và có thể tránh bất kỳ sao chép nào.

Các phương thức Reader.ResetWriter.Reset hiện sử dụng kích thước buffer mặc định khi được gọi trên các đối tượng với buffer nil.

bytes

Hàm mới Cut cắt []byte quanh một dấu phân cách. Nó có thể thay thế và đơn giản hóa nhiều cách sử dụng phổ biến của Index, IndexByte, IndexRuneSplitN.

Trim, TrimLeftTrimRight hiện không cấp phát bộ nhớ và, đặc biệt với các cutset ASCII nhỏ, nhanh hơn tới 10 lần.

Hàm Title hiện bị deprecated. Nó không xử lý dấu câu Unicode và các quy tắc viết hoa theo ngôn ngữ, và được thay thế bởi package golang.org/x/text/cases.

crypto/elliptic

Các triển khai đường cong P224, P384P521 hiện tất cả được hỗ trợ bởi code được tạo ra bởi các dự án addchainfiat-crypto, dự án sau dựa trên một mô hình được xác minh chính thức về các thao tác số học. Chúng hiện sử dụng các công thức đầy đủ an toàn hơn và các API nội bộ. P-224 và P-384 hiện nhanh hơn khoảng bốn lần. Tất cả các triển khai đường cong cụ thể hiện có thời gian cố định.

Hoạt động trên các điểm đường cong không hợp lệ (những điểm mà phương thức IsOnCurve trả về false, và không bao giờ được trả về bởi Unmarshal hoặc một phương thức Curve hoạt động trên một điểm hợp lệ) luôn là hành vi không xác định, có thể dẫn đến các cuộc tấn công khôi phục key và hiện không được hỗ trợ bởi backend mới. Nếu một điểm không hợp lệ được cung cấp cho một phương thức P224, P384 hoặc P521, phương thức đó hiện sẽ trả về một điểm ngẫu nhiên. Hành vi có thể thay đổi thành một panic tường minh trong một bản phát hành tương lai.

crypto/tls

Phương thức mới Conn.NetConn cho phép truy cập vào net.Conn nền.

crypto/x509

Certificate.Verify hiện sử dụng các API nền tảng để xác minh tính hợp lệ của chứng chỉ trên macOS và iOS khi nó được gọi với VerifyOpts.Roots nil hoặc khi sử dụng pool root được trả về từ SystemCertPool.

SystemCertPool hiện có sẵn trên Windows.

Trên Windows, macOS và iOS, khi một CertPool được trả về bởi SystemCertPool có thêm các chứng chỉ được thêm vào, Certificate.Verify sẽ thực hiện hai xác minh: một sử dụng các API xác minh nền tảng và các root hệ thống, và một sử dụng verifier Go và các root bổ sung. Các chuỗi được trả về bởi các API xác minh nền tảng sẽ được ưu tiên.

CertPool.Subjects bị deprecated. Trên Windows, macOS và iOS, CertPool được trả về bởi SystemCertPool sẽ trả về một pool không bao gồm các root hệ thống trong slice được trả về bởi Subjects, vì danh sách tĩnh không thể đại diện đúng cho các chính sách nền tảng và có thể không có sẵn từ các API nền tảng.

Hỗ trợ ký các chứng chỉ bằng các thuật toán chữ ký phụ thuộc vào hàm băm MD5 (MD5WithRSA) có thể bị xóa trong Go 1.19.

debug/dwarf

Các struct StructFieldBasicType giờ đều có trường DataBitOffset, giữ giá trị của thuộc tính DW_AT_data_bit_offset nếu có.

debug/elf

Hằng số R_PPC64_RELATIVE đã được thêm vào.

debug/plan9obj

Phương thức File.Symbols hiện trả về giá trị lỗi được xuất ra mới ErrNoSymbols nếu file không có phần symbol.

embed

Một chỉ thị go:embed hiện có thể bắt đầu với all: để bao gồm các file có tên bắt đầu bằng dấu chấm hoặc dấu gạch dưới.

go/ast

Theo đề xuất Bổ sung vào go/ast và go/token để hỗ trợ các hàm và kiểu được tham số hóa các bổ sung sau được thực hiện vào package go/ast:

  • Các node FuncTypeTypeSpec có trường TypeParams mới để giữ các tham số kiểu, nếu có.
  • Node biểu thức mới IndexListExpr đại diện cho các biểu thức chỉ mục với nhiều chỉ mục, được sử dụng cho các lần khởi tạo hàm và kiểu với nhiều hơn một đối số kiểu tường minh.

go/constant

Phương thức mới Kind.String trả về tên đọc được bởi con người cho kind của receiver.

go/token

Hằng số mới TILDE đại diện cho token ~ theo đề xuất Bổ sung vào go/ast và go/token để hỗ trợ các hàm và kiểu được tham số hóa.

go/types

Trường mới Config.GoVersion đặt phiên bản ngôn ngữ Go được chấp nhận.

Theo đề xuất Bổ sung vào go/types để hỗ trợ các tham số kiểu các bổ sung sau được thực hiện vào package go/types:

  • Kiểu mới TypeParam, hàm factory NewTypeParam và các phương thức liên quan được thêm vào để đại diện cho tham số kiểu.
  • Kiểu mới TypeParamList giữ danh sách tham số kiểu.
  • Kiểu mới TypeList giữ danh sách các kiểu.
  • Hàm factory mới NewSignatureType cấp phát một Signature với các tham số kiểu (receiver hoặc hàm). Để truy cập các tham số kiểu đó, kiểu Signature có hai phương thức mới Signature.RecvTypeParamsSignature.TypeParams.
  • Các kiểu Named có bốn phương thức mới: Named.Origin để lấy các kiểu tham số hóa ban đầu của các kiểu được khởi tạo, Named.TypeArgsNamed.TypeParams để lấy các đối số kiểu hoặc tham số kiểu của kiểu được khởi tạo hoặc tham số hóa, và Named.SetTypeParams để đặt các tham số kiểu (ví dụ, khi import một kiểu có tên nơi mà việc cấp phát kiểu có tên và đặt các tham số kiểu không thể được thực hiện đồng thời do các chu kỳ có thể xảy ra).
  • Kiểu Interface có bốn phương thức mới: Interface.IsComparableInterface.IsMethodSet để truy vấn các thuộc tính của tập kiểu được định nghĩa bởi interface, và Interface.MarkImplicitInterface.IsImplicit để đặt và kiểm tra liệu interface có phải là interface ngầm quanh một type constraint literal hay không.
  • Các kiểu mới UnionTerm, các hàm factory NewUnionNewTerm và các phương thức liên quan được thêm vào để đại diện cho các tập kiểu trong interface.
  • Hàm mới Instantiate khởi tạo một kiểu được tham số hóa.
  • Map Info.Instances mới ghi lại các lần khởi tạo hàm và kiểu thông qua kiểu Instance mới.
  • Kiểu mới ArgumentError và các phương thức liên quan được thêm vào để đại diện cho lỗi liên quan đến đối số kiểu.
  • Kiểu mới Context và hàm factory NewContext được thêm vào để tạo điều kiện chia sẻ các instance kiểu giống hệt nhau giữa các package đã được kiểm tra kiểu, thông qua trường Config.Context mới.

Các vị từ AssignableTo, ConvertibleTo, Implements, Identical, IdenticalIgnoreTagsAssertableTo hiện cũng hoạt động với các đối số là hoặc chứa các interface tổng quát, tức là các interface chỉ có thể được sử dụng làm ràng buộc kiểu trong code Go. Lưu ý rằng hành vi của AssignableTo, ConvertibleTo, ImplementsAssertableTo không xác định với các đối số là các kiểu generic chưa được khởi tạo, và AssertableTo không xác định nếu đối số đầu tiên là một interface tổng quát.

html/template

Trong pipeline range, lệnh mới {{break}} sẽ kết thúc vòng lặp sớm và lệnh mới {{continue}} sẽ ngay lập tức bắt đầu vòng lặp tiếp theo.

Hàm and không còn luôn luôn đánh giá tất cả các đối số; nó ngừng đánh giá các đối số sau đối số đầu tiên đánh giá thành false. Tương tự, hàm or hiện ngừng đánh giá các đối số sau đối số đầu tiên đánh giá thành true. Điều này tạo ra sự khác biệt nếu bất kỳ đối số nào là một lời gọi hàm.

image/draw

Các triển khai dự phòng DrawDrawMask (được sử dụng khi các đối số không phải là các kiểu image phổ biến nhất) hiện nhanh hơn khi các đối số đó triển khai tùy chọn draw.RGBA64Imageimage.RGBA64Image được thêm vào trong Go 1.17.

net

net.Error.Temporary đã bị deprecated.

net/http

Trên các mục tiêu WebAssembly, các trường phương thức Dial, DialContext, DialTLSDialTLSContext trong Transport hiện sẽ được sử dụng đúng cách, nếu được chỉ định, để thực hiện các yêu cầu HTTP.

Phương thức mới Cookie.Valid báo cáo liệu cookie có hợp lệ hay không.

Hàm mới MaxBytesHandler tạo một Handler bao bọc ResponseWriterRequest.Body của nó với một MaxBytesReader.

Khi tra cứu tên miền chứa các ký tự không phải ASCII, việc chuyển đổi Unicode sang ASCII hiện được thực hiện theo Nontransitional Processing như được định nghĩa trong tiêu chuẩn Xử lý tương thích Unicode IDNA (UTS #46). Cách diễn giải của bốn rune riêng biệt bị thay đổi: ß, ς, zero-width joiner U+200D và zero-width non-joiner U+200C. Nontransitional Processing nhất quán với hầu hết các ứng dụng và trình duyệt web.

os/user

User.GroupIds hiện sử dụng triển khai Go gốc khi cgo không có sẵn.

reflect

Các phương thức mới Value.SetIterKeyValue.SetIterValue đặt Value bằng cách sử dụng map iterator như nguồn. Chúng tương đương với Value.Set(iter.Key())Value.Set(iter.Value()), nhưng thực hiện ít cấp phát hơn.

Phương thức mới Value.UnsafePointer trả về giá trị của Value như một unsafe.Pointer. Điều này cho phép người gọi migrate từ Value.UnsafeAddrValue.Pointer để loại bỏ nhu cầu thực hiện chuyển đổi uintptr sang unsafe.Pointer tại callsite (như các quy tắc unsafe.Pointer yêu cầu).

Phương thức mới MapIter.Reset thay đổi receiver của nó để lặp qua một map khác. Việc sử dụng MapIter.Reset cho phép lặp không cấp phát qua nhiều map.

Một số phương thức ( Value.CanInt, Value.CanUint, Value.CanFloat, Value.CanComplex ) đã được thêm vào Value để kiểm tra liệu một chuyển đổi có an toàn không.

Value.FieldByIndexErr đã được thêm vào để tránh panic xảy ra trong Value.FieldByIndex khi bước qua con trỏ nil đến một struct được nhúng.

reflect.Ptrreflect.PtrTo đã được đổi tên thành reflect.Pointerreflect.PointerTo, tương ứng, để nhất quán với phần còn lại của package reflect. Các tên cũ sẽ tiếp tục hoạt động, nhưng sẽ bị deprecated trong một bản phát hành Go trong tương lai.

regexp

regexp hiện coi mỗi byte không hợp lệ của chuỗi UTF-8 là U+FFFD.

runtime/debug

Struct BuildInfo có hai trường mới, chứa thông tin bổ sung về cách nhị phân được build:

  • GoVersion giữ phiên bản Go được sử dụng để build nhị phân.
  • Settings là một slice của các struct BuildSettings giữ các cặp key/value mô tả build.

runtime/pprof

CPU profiler hiện sử dụng timer theo luồng trên Linux. Điều này tăng mức sử dụng CPU tối đa mà một profile có thể quan sát, và giảm một số dạng thiên lệch.

strconv

strconv.Unquote hiện từ chối các nửa surrogate Unicode.

strings

Hàm mới Cut cắt string quanh một dấu phân cách. Nó có thể thay thế và đơn giản hóa nhiều cách sử dụng phổ biến của Index, IndexByte, IndexRuneSplitN.

Hàm mới Clone sao chép string đầu vào mà không để string được clone được trả về tham chiếu bộ nhớ của chuỗi đầu vào.

Trim, TrimLeftTrimRight hiện không cấp phát bộ nhớ và, đặc biệt với các cutset ASCII nhỏ, nhanh hơn tới 10 lần.

Hàm Title hiện bị deprecated. Nó không xử lý dấu câu Unicode và các quy tắc viết hoa theo ngôn ngữ, và được thay thế bởi package golang.org/x/text/cases.

sync

Các phương thức mới Mutex.TryLock, RWMutex.TryLockRWMutex.TryRLock, sẽ giành được lock nếu nó không đang được giữ.

syscall

Hàm mới SyscallN đã được giới thiệu cho Windows, cho phép gọi với số lượng đối số tùy ý. Do đó, Syscall, Syscall6, Syscall9, Syscall12, Syscall15Syscall18 bị deprecated để ủng hộ SyscallN.

SysProcAttr.Pdeathsig hiện được hỗ trợ trên FreeBSD.

syscall/js

Interface Wrapper đã bị xóa.

testing

Ưu tiên của / trong đối số cho -run-bench đã được tăng lên. A/B|C/D từng được coi là A/(B|C)/D và hiện được coi là (A/B)|(C/D).

Nếu tùy chọn -run không chọn bất kỳ test nào, tùy chọn -count bị bỏ qua. Điều này có thể thay đổi hành vi của các test hiện có trong trường hợp khó xảy ra khi một test thay đổi tập hợp các subtest được chạy mỗi lần hàm test chính nó được chạy.

Kiểu mới testing.F được sử dụng bởi hỗ trợ fuzzing mới được mô tả ở trên. Các test hiện cũng hỗ trợ các tùy chọn dòng lệnh -test.fuzz, -test.fuzztime-test.fuzzminimizetime.

text/template

Trong pipeline range, lệnh mới {{break}} sẽ kết thúc vòng lặp sớm và lệnh mới {{continue}} sẽ ngay lập tức bắt đầu vòng lặp tiếp theo.

Hàm and không còn luôn luôn đánh giá tất cả các đối số; nó ngừng đánh giá các đối số sau đối số đầu tiên đánh giá thành false. Tương tự, hàm or hiện ngừng đánh giá các đối số sau đối số đầu tiên đánh giá thành true. Điều này tạo ra sự khác biệt nếu bất kỳ đối số nào là một lời gọi hàm.

text/template/parse

Package hỗ trợ lệnh {{break}} mới của text/templatehtml/template thông qua hằng số mới NodeBreak và kiểu mới BreakNode, và tương tự hỗ trợ lệnh {{continue}} mới thông qua hằng số mới NodeContinue và kiểu mới ContinueNode.

unicode/utf8

Hàm mới AppendRune thêm mã hóa UTF-8 của một rune vào một []byte.