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àm và kiể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
anylà 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
comparablelà 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,imagvàcomplex. 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
mtrên giá trịxcủa kiểu tham số kiểuPnếumđược khai báo tường minh bởi interface ràng buộc củaP. Tương tự, các giá trị phương thứcx.mvà các biểu thức phương thứcP.mcũng chỉ được hỗ trợ nếumđược khai báo tường minh bởiP, mặc dùmcó thể nằm trong tập phương thức củaPdo tất cả các kiểu trongPđều triển khaim. 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.fkhixcó 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ườngf. 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
print và println, 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-archive và c-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/arm và windows/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.mod và go.sum
Các lệnh con go mod graph,
go mod vendor,
go mod verify và
go mod why
không còn tự động cập nhật các file go.mod và
go.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 testhỗ trợ các tùy chọn-fuzz,-fuzztimevà-fuzzminimizetime. Để biết tài liệu về những điều này, xemgo help testflag.go cleanhỗ trợ tùy chọn-fuzzcache. Để biết tài liệu, xemgo 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, testinggoroutine và tests
đề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.Reset và
Writer.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,
IndexRune
và SplitN.
Trim, TrimLeft
và TrimRight 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,
P384 và
P521
hiện tất cả được hỗ trợ bởi code được tạo ra bởi các dự án
addchain và
fiat-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 StructField
và BasicType
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
FuncTypevàTypeSpeccó trườngTypeParamsmớ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 factoryNewTypeParamvà 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
TypeParamListgiữ danh sách tham số kiểu. - Kiểu mới
TypeListgiữ danh sách các kiểu. - Hàm factory mới
NewSignatureTypecấp phát mộtSignaturevới các tham số kiểu (receiver hoặc hàm). Để truy cập các tham số kiểu đó, kiểuSignaturecó hai phương thức mớiSignature.RecvTypeParamsvàSignature.TypeParams. - Các kiểu
Namedcó 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.TypeArgsvàNamed.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
Interfacecó bốn phương thức mới:Interface.IsComparablevàInterface.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.MarkImplicitvàInterface.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
UnionvàTerm, các hàm factoryNewUnionvàNewTermvà 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
Instantiatekhởi tạo một kiểu được tham số hóa. - Map
Info.Instancesmới ghi lại các lần khởi tạo hàm và kiểu thông qua kiểuInstancemới. -
Kiểu mới
ArgumentErrorvà 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
Contextvà hàm factoryNewContextđượ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ườngConfig.Contextmới.
Các vị từ
AssignableTo,
ConvertibleTo,
Implements,
Identical,
IdenticalIgnoreTags và
AssertableTo
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, Implements và
AssertableTo 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 Draw và DrawMask
(đượ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.RGBA64Image
và image.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,
DialTLS và DialTLSContext 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 ResponseWriter và
Request.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.SetIterKey
và Value.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()) và 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.UnsafeAddr
và Value.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.Ptr và
reflect.PtrTo
đã được đổi tên thành
reflect.Pointer và
reflect.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:
GoVersiongiữ phiên bản Go được sử dụng để build nhị phân.Settingslà một slice của các structBuildSettingsgiữ 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,
IndexRune
và SplitN.
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, TrimLeft
và TrimRight 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.TryLock và
RWMutex.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,
Syscall15 và
Syscall18 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 và
-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 và
-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/template và
html/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.