Ghi chú phát hành Go 1.14
Giới thiệu về Go 1.14
Bản phát hành Go mới nhất, phiên bản 1.14, ra đời sáu tháng sau Go 1.13. Hầu hết các thay đổi nằm ở phần triển khai của bộ công cụ, runtime và thư viện. Như thường lệ, bản phát hành vẫn 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.
Hỗ trợ module trong lệnh go hiện sẵn sàng cho môi trường production, và chúng tôi khuyến khích tất cả người dùng di chuyển sang Go modules để quản lý dependency. Nếu bạn không thể di chuyển do sự cố trong bộ công cụ Go, hãy đảm bảo rằng sự cố đó có issue đang mở được ghi nhận. (Nếu issue không thuộc milestone Go1.15, hãy cho chúng tôi biết lý do nó ngăn bạn di chuyển để chúng tôi có thể ưu tiên phù hợp.)
Thay đổi ngôn ngữ
Theo đề xuất về interface chồng lấp, Go 1.14 giờ cho phép nhúng các interface có tập phương thức chồng lấp: các phương thức từ interface được nhúng có thể có cùng tên và chữ ký giống hệt với các phương thức đã có trong interface (nhúng). Điều này giải quyết các vấn đề thường xảy ra (nhưng không phải độc quyền) với đồ thị nhúng hình kim cương. Các phương thức được khai báo tường minh trong interface phải vẫn duy nhất, như trước.
Các nền tảng
Darwin
Go 1.14 là bản phát hành cuối cùng chạy trên macOS 10.11 El Capitan. Go 1.15 sẽ yêu cầu macOS 10.12 Sierra hoặc mới hơn.
Go 1.14 là bản phát hành Go cuối cùng hỗ trợ tệp nhị phân 32-bit trên macOS (cổng darwin/386). Chúng không còn được macOS hỗ trợ, bắt đầu từ macOS 10.15 (Catalina). Go tiếp tục hỗ trợ cổng 64-bit darwin/amd64.
Go 1.14 có thể là bản phát hành Go cuối cùng hỗ trợ tệp nhị phân 32-bit trên iOS, iPadOS, watchOS và tvOS (cổng darwin/arm). Go tiếp tục hỗ trợ cổng 64-bit darwin/arm64.
Windows
Các tệp nhị phân Go trên Windows giờ có DEP (Data Execution Prevention) được bật.
Trên Windows, tạo tệp qua os.OpenFile với cờ os.O_CREATE, hoặc qua syscall.Open với cờ syscall.O_CREAT, giờ sẽ tạo tệp chỉ đọc nếu bit 0o200 (quyền ghi của owner) không được đặt trong tham số quyền. Điều này làm cho hành vi trên Windows giống hơn với Unix.
WebAssembly
Các giá trị JavaScript được tham chiếu từ Go qua các đối tượng js.Value giờ có thể được bộ gom rác thu hồi.
Các giá trị js.Value không còn có thể so sánh bằng toán tử ==, và thay vào đó phải so sánh bằng phương thức Equal của chúng.
js.Value giờ có các phương thức IsUndefined, IsNull và IsNaN.
RISC-V
Go 1.14 có hỗ trợ thực nghiệm cho 64-bit RISC-V trên Linux (GOOS=linux, GOARCH=riscv64). Lưu ý rằng hiệu năng, tính ổn định cú pháp assembly và có thể cả tính đúng đắn vẫn đang được phát triển.
FreeBSD
Go giờ hỗ trợ kiến trúc ARM 64-bit trên FreeBSD 12.0 hoặc mới hơn (cổng freebsd/arm64).
Native Client (NaCl)
Như đã thông báo trong ghi chú phát hành Go 1.13,
Go 1.14 bỏ hỗ trợ nền tảng Native Client (GOOS=nacl).
Illumos
Runtime giờ tôn trọng giới hạn CPU của zone (zone.cpu-cap resource control) cho runtime.NumCPU và giá trị mặc định của GOMAXPROCS.
Công cụ
Lệnh Go
Vendoring
Khi module chính chứa thư mục vendor cấp cao nhất và tệp go.mod của nó chỉ định go 1.14 hoặc cao hơn, lệnh go giờ mặc định là -mod=vendor cho các thao tác chấp nhận cờ đó. Giá trị mới cho cờ đó, -mod=mod, khiến lệnh go tải module từ module cache (như khi không có thư mục vendor).
Khi -mod=vendor được đặt (tường minh hay mặc định), lệnh go giờ xác minh rằng tệp vendor/modules.txt của module chính nhất quán với tệp go.mod của nó.
go list -m không còn âm thầm bỏ qua các dependency bắc cầu không cung cấp gói trong thư mục vendor. Nó giờ thất bại tường minh nếu -mod=vendor được đặt và thông tin được yêu cầu cho module không được đề cập trong vendor/modules.txt.
Các cờ
Lệnh go get không còn chấp nhận cờ -mod. Trước đây, cài đặt của cờ này hoặc bị bỏ qua hoặc khiến build thất bại.
-mod=readonly giờ được đặt mặc định khi tệp go.mod là chỉ đọc và không có thư mục vendor cấp cao nhất.
-modcacherw là cờ mới chỉ thị lệnh go để giữ các thư mục mới tạo trong module cache với quyền mặc định thay vì làm chúng chỉ đọc.
Việc dùng cờ này làm tăng khả năng các test hoặc công cụ khác vô tình thêm tệp không được bao gồm trong checksum đã xác minh của module. Tuy nhiên, nó cho phép dùng rm -rf (thay vì go clean -modcache) để xóa module cache.
-modfile=file là cờ mới chỉ thị lệnh go đọc (và có thể ghi) tệp go.mod thay thế thay vì tệp trong thư mục gốc của module. Tệp tên go.mod vẫn phải có để xác định thư mục gốc module, nhưng không được truy cập. Khi -modfile được chỉ định, tệp go.sum thay thế cũng được dùng: đường dẫn của nó được dẫn xuất từ cờ -modfile bằng cách cắt đuôi .mod và thêm .sum.
Biến môi trường
GOINSECURE là biến môi trường mới chỉ thị lệnh go không yêu cầu kết nối HTTPS, và bỏ qua xác thực chứng chỉ, khi lấy trực tiếp một số module từ nguồn của chúng. Giống như biến GOPRIVATE hiện có, giá trị của GOINSECURE là danh sách phân cách bằng dấu phẩy các mẫu glob.
Các lệnh ngoài module
Khi chế độ module-aware được bật tường minh (bằng cách đặt GO111MODULE=on), hầu hết các lệnh module có chức năng hạn chế hơn nếu không có tệp go.mod. Ví dụ, go build, go run và các lệnh build khác chỉ có thể build các gói trong thư viện chuẩn và các gói được chỉ định dưới dạng tệp .go trên dòng lệnh.
Trước đây, lệnh go phân giải từng đường dẫn gói thành phiên bản mới nhất của module nhưng không ghi lại đường dẫn module hay phiên bản. Điều này dẫn đến các build chậm, không tái lập được.
go get tiếp tục hoạt động như trước, cũng như go mod download và go list -m với phiên bản tường minh.
Phiên bản +incompatible
Nếu phiên bản mới nhất của module chứa tệp go.mod, go get sẽ không còn nâng cấp lên phiên bản major không tương thích của module đó trừ khi phiên bản đó được yêu cầu tường minh hoặc đã được yêu cầu. go list cũng bỏ qua các phiên bản major không tương thích cho module đó khi lấy trực tiếp từ kiểm soát phiên bản, nhưng có thể bao gồm chúng nếu được báo cáo bởi proxy.
Bảo trì tệp go.mod
Các lệnh go khác ngoài go mod tidy không còn xóa directive require chỉ định phiên bản dependency gián tiếp đã được ngụ ý bởi các dependency (bắc cầu) khác của module chính.
Các lệnh go khác ngoài go mod tidy không còn chỉnh sửa tệp go.mod nếu các thay đổi chỉ là thẩm mỹ.
Khi -mod=readonly được đặt, các lệnh go sẽ không còn thất bại do directive go bị thiếu hoặc comment // indirect có lỗi.
Tải xuống module
Lệnh go giờ hỗ trợ kho lưu trữ Subversion trong chế độ module.
Lệnh go giờ bao gồm các đoạn thông báo lỗi văn bản thuần từ các module proxy và các máy chủ HTTP khác.
Thông báo lỗi chỉ được hiển thị nếu nó là UTF-8 hợp lệ và chỉ bao gồm các ký tự đồ họa và dấu cách.
Kiểm thử
go test -v giờ phát trực tiếp đầu ra t.Log ngay khi xảy ra, thay vì ở cuối tất cả các test.
Runtime
Bản phát hành này cải thiện hiệu năng của hầu hết các lần dùng defer để gánh chịu gần như không có overhead so với gọi trực tiếp hàm được defer. Do đó, defer giờ có thể được dùng trong mã nhạy cảm về hiệu năng mà không lo overhead.
Goroutine giờ có thể bị preempt bất đồng bộ. Do đó, các vòng lặp không có lời gọi hàm không còn có thể làm nghẽn scheduler hoặc trì hoãn đáng kể bộ gom rác. Điều này được hỗ trợ trên tất cả nền tảng ngoại trừ windows/arm, darwin/arm, js/wasm và plan9/*.
Hậu quả của việc triển khai preemption là trên hệ thống Unix, bao gồm Linux và macOS, các chương trình được build với Go 1.14 sẽ nhận nhiều tín hiệu hơn so với các chương trình được build với các bản phát hành trước. Điều này có nghĩa là các chương trình sử dụng các gói như syscall hoặc golang.org/x/sys/unix sẽ thấy nhiều lời gọi hệ thống chậm thất bại với lỗi EINTR hơn. Những chương trình đó sẽ phải xử lý các lỗi đó theo cách nào đó, thường là lặp lại để thử lại lời gọi hệ thống. Để biết thêm thông tin, xem man 7 signal cho hệ thống Linux hoặc tài liệu tương tự cho các hệ thống khác.
Trình cấp phát trang hiệu quả hơn và gánh chịu tranh chấp lock ít hơn đáng kể ở các giá trị cao của GOMAXPROCS. Điều này rõ nhất nhất là độ trễ thấp hơn và thông lượng cao hơn cho các cấp phát lớn được thực hiện song song với tốc độ cao.
Bộ đếm thời gian nội bộ, được dùng bởi time.After, time.Tick, net.Conn.SetDeadline và các hàm tương tự, hiệu quả hơn, với ít tranh chấp lock hơn và ít context switch hơn. Đây là cải tiến hiệu năng không gây ra thay đổi nào hiển thị với người dùng.
Trình biên dịch
Bản phát hành này thêm -d=checkptr như một tùy chọn compile-time để thêm instrumentation kiểm tra rằng mã Go đang tuân theo các quy tắc an toàn unsafe.Pointer một cách động. Tùy chọn này được bật theo mặc định (ngoại trừ trên Windows) với các cờ -race hoặc -msan, và có thể tắt bằng -gcflags=all=-d=checkptr=0.
Cụ thể, -d=checkptr kiểm tra những điều sau:
- Khi chuyển đổi
unsafe.Pointerthành*T, con trỏ kết quả phải được căn chỉnh phù hợp vớiT. - Nếu kết quả của phép tính con trỏ trỏ vào đối tượng heap Go, một trong các toán hạng kiểu
unsafe.Pointerphải trỏ vào cùng đối tượng.
Hiện không khuyến nghị dùng -d=checkptr trên Windows vì nó gây ra cảnh báo sai trong thư viện chuẩn.
Trình biên dịch giờ có thể phát ra log có thể đọc bằng máy về các tối ưu hóa chính bằng cờ -json, bao gồm inlining, phân tích thoát, loại bỏ kiểm tra giới hạn và loại bỏ kiểm tra nil.
Chẩn đoán phân tích thoát chi tiết (-m=2) giờ hoạt động lại. Điều này đã bị bỏ khỏi triển khai phân tích thoát mới trong bản phát hành trước.
Tất cả ký hiệu Go trong tệp nhị phân macOS giờ bắt đầu bằng dấu gạch dưới, theo quy ước của nền tảng.
Bản phát hành này bao gồm hỗ trợ thực nghiệm cho instrumentation coverage do trình biên dịch chèn vào cho fuzzing. Xem issue 14565 để biết thêm chi tiết. API này có thể thay đổi trong các bản phát hành tương lai.
Loại bỏ kiểm tra giới hạn giờ dùng thông tin từ việc tạo slice và có thể loại bỏ kiểm tra cho các chỉ số có kiểu nhỏ hơn int.
Thư viện chuẩn
Gói hashing chuỗi byte mới
Go 1.14 bao gồm gói mới hash/maphash, cung cấp các hàm hash trên chuỗi byte. Các hàm hash này dự định dùng để triển khai bảng hash hoặc các cấu trúc dữ liệu khác cần ánh xạ chuỗi tùy ý hoặc chuỗi byte sang phân phối đồng đều trên các số nguyên 64-bit không dấu.
Các hàm hash có khả năng chống va chạm nhưng không bảo mật mật mã.
Giá trị hash của một chuỗi byte nhất định nhất quán trong một tiến trình, nhưng sẽ khác nhau trong các tiến trình khác nhau.
Thay đổi nhỏ trong thư viện
Như thường lệ, 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 trong tâm trí.
crypto/tls
Hỗ trợ cho SSL phiên bản 3.0 (SSLv3) đã bị xóa. Lưu ý rằng SSLv3 là giao thức bị phá vỡ về mặt mật mã có trước TLS.
TLS 1.3 không thể bị tắt qua biến môi trường GODEBUG nữa. Dùng trường Config.MaxVersion để cấu hình phiên bản TLS.
Khi nhiều chuỗi chứng chỉ được cung cấp qua trường Config.Certificates, chuỗi đầu tiên tương thích với peer giờ được tự động chọn. Điều này cho phép ví dụ cung cấp chứng chỉ ECDSA và RSA, và để gói tự động chọn cái tốt nhất. Lưu ý rằng hiệu năng của việc chọn này sẽ kém trừ khi trường Certificate.Leaf được đặt. Trường Config.NameToCertificate, chỉ hỗ trợ liên kết một chứng chỉ với tên đã cho, giờ bị deprecated và nên để là nil. Tương tự, phương thức Config.BuildNameToCertificate, xây dựng trường NameToCertificate từ các chứng chỉ leaf, giờ bị deprecated và không nên được gọi.
Các hàm mới CipherSuites và InsecureCipherSuites trả về danh sách các cipher suite hiện được triển khai. Hàm mới CipherSuiteName trả về tên cho ID cipher suite.
Các phương thức mới (*ClientHelloInfo).SupportsCertificate và (*CertificateRequestInfo).SupportsCertificate cho biết liệu peer có hỗ trợ chứng chỉ nhất định không.
Gói tls không còn hỗ trợ tiện ích mở rộng Next Protocol Negotiation (NPN) kế thừa và giờ chỉ hỗ trợ ALPN. Trong các bản phát hành trước, nó hỗ trợ cả hai. Không có thay đổi API và các ứng dụng sẽ hoạt động giống hệt như trước. Hầu hết các client và server khác đã xóa hỗ trợ NPN để ưu tiên ALPN chuẩn hóa.
Chữ ký RSA-PSS giờ được dùng khi được hỗ trợ trong TLS 1.2 handshake. Điều này sẽ không ảnh hưởng đến hầu hết ứng dụng, nhưng các triển khai Certificate.PrivateKey tùy chỉnh không hỗ trợ chữ ký RSA-PSS sẽ cần dùng trường Certificate.SupportedSignatureAlgorithms mới để tắt chúng.
Config.Certificates và Config.GetCertificate giờ đều có thể là nil nếu Config.GetConfigForClient được đặt. Nếu callback không trả về chứng chỉ cũng không có lỗi, unrecognized_name giờ được gửi.
Trường mới CertificateRequestInfo.Version cung cấp phiên bản TLS cho callback chứng chỉ client.
Các hằng số mới TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 và TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 dùng tên cuối cùng cho các cipher suite trước đây gọi là TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 và TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305.
crypto/x509
Certificate.CreateCRL
giờ hỗ trợ issuer Ed25519.
debug/dwarf
Gói debug/dwarf giờ hỗ trợ đọc DWARF phiên bản 5.
Phương thức mới (*Data).AddSection hỗ trợ thêm các section DWARF tùy ý mới từ tệp đầu vào vào Data DWARF.
Phương thức mới (*Reader).ByteOrder trả về thứ tự byte của đơn vị biên dịch hiện tại. Điều này có thể dùng để diễn giải các thuộc tính được mã hóa theo thứ tự gốc, chẳng hạn như mô tả vị trí.
Phương thức mới (*LineReader).Files trả về bảng tên tệp từ line reader. Điều này có thể dùng để diễn giải giá trị của các thuộc tính DWARF như AttrDeclFile.
encoding/asn1
Unmarshal giờ hỗ trợ kiểu chuỗi ASN.1 BMPString, được biểu diễn bởi hằng số mới TagBMPString.
encoding/json
Kiểu Decoder hỗ trợ phương thức mới InputOffset trả về offset byte trong luồng đầu vào của vị trí decoder hiện tại.
Compact không còn thoát các ký tự U+2028 và U+2029, vốn không bao giờ là tính năng được ghi lại. Để thoát đúng cách, xem HTMLEscape.
Number không còn chấp nhận các số không hợp lệ, để tuân theo hành vi được ghi lại chính xác hơn. Nếu chương trình cần chấp nhận các số không hợp lệ như chuỗi rỗng, hãy xem xét bọc kiểu bằng Unmarshaler.
Unmarshal giờ có thể hỗ trợ các key map với kiểu cơ sở là chuỗi triển khai encoding.TextUnmarshaler.
go/build
Kiểu Context có trường mới Dir có thể dùng để đặt thư mục làm việc cho build. Mặc định là thư mục hiện tại của tiến trình đang chạy. Trong chế độ module, điều này được dùng để xác định module chính.
go/doc
Hàm mới NewFromFiles tính tài liệu gói từ danh sách *ast.File và liên kết các ví dụ với phần tử gói phù hợp. Thông tin mới có trong trường Examples mới trong các kiểu Package, Type và Func, và trường Suffix mới trong kiểu Example.
io/ioutil
TempDir giờ có thể tạo các thư mục có tên với tiền tố và hậu tố có thể dự đoán. Cũng như TempFile, nếu pattern chứa ‘*’, chuỗi ngẫu nhiên thay thế ‘*’ cuối cùng.
log
Cờ mới Lmsgprefix có thể dùng để yêu cầu các hàm logging phát tiền tố đầu ra tùy chọn ngay trước thông báo log thay vì ở đầu dòng.
math
Hàm mới FMA tính x*y+z trong số thực mà không có làm tròn trung gian của phép tính x*y. Một số kiến trúc triển khai phép tính này bằng các lệnh phần cứng chuyên dụng để có hiệu năng bổ sung.
math/big
Phương thức GCD giờ cho phép đầu vào a và b là không hoặc âm.
math/bits
Các hàm mới Rem, Rem32 và Rem64 hỗ trợ tính số dư ngay cả khi số nguyên tràn.
mime
Kiểu mặc định của tệp .js và .mjs giờ là text/javascript thay vì application/javascript. Điều này phù hợp với bản nháp IETF coi application/javascript là lỗi thời.
mime/multipart
Phương thức mới NextRawPart của Reader hỗ trợ lấy phần MIME tiếp theo mà không giải mã quoted-printable trong suốt.
net/http
Phương thức mới Values của Header có thể dùng để lấy tất cả giá trị liên kết với key đã chuẩn hóa.
Trường mới DialTLSContext của Transport có thể dùng để chỉ định hàm dial tùy chọn để tạo kết nối TLS cho các request HTTPS không qua proxy. Trường mới này có thể dùng thay cho DialTLS, vốn giờ được coi là deprecated; DialTLS vẫn tiếp tục hoạt động, nhưng mã mới nên dùng DialTLSContext, cho phép transport hủy dial ngay khi chúng không còn cần thiết.
Trên Windows, ServeFile giờ phục vụ đúng các tệp lớn hơn 2GB.
net/http/httptest
Trường mới EnableHTTP2 của Server hỗ trợ bật HTTP/2 trên máy chủ test.
net/textproto
Phương thức mới Values của MIMEHeader có thể dùng để lấy tất cả giá trị liên kết với key đã chuẩn hóa.
net/url
Khi phân tích URL thất bại (ví dụ bởi Parse hoặc ParseRequestURI), thông báo Error kết quả giờ sẽ trích dẫn URL không thể phân tích được. Điều này cung cấp cấu trúc rõ ràng hơn và nhất quán với các lỗi phân tích khác.
os/signal
Trên Windows, các sự kiện CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT và CTRL_SHUTDOWN_EVENT giờ tạo ra tín hiệu syscall.SIGTERM, tương tự như cách Control-C và Control-Break tạo ra tín hiệu syscall.SIGINT.
plugin
Gói plugin giờ hỗ trợ freebsd/amd64.
reflect
StructOf giờ hỗ trợ tạo các kiểu struct với trường không xuất (unexported), bằng cách đặt trường PkgPath trong phần tử StructField.
runtime
runtime.Goexit không còn có thể bị hủy bởi panic/recover đệ quy.
Trên macOS, SIGPIPE không còn được chuyển tiếp đến các handler tín hiệu được cài đặt trước khi Go runtime được khởi tạo. Điều này cần thiết vì macOS gửi SIGPIPE đến luồng chính thay vì luồng đang ghi vào pipe đã đóng.
runtime/pprof
Profile được tạo ra không còn bao gồm các pseudo-PC dùng cho các dấu inline. Thông tin ký hiệu của các hàm inline được mã hóa theo định dạng mà công cụ pprof mong đợi. Đây là bản vá lỗi hồi quy được đưa ra trong các bản phát hành gần đây.
strconv
Kiểu NumError giờ có phương thức Unwrap có thể dùng để lấy lý do chuyển đổi thất bại. Điều này hỗ trợ dùng giá trị NumError với errors.Is để xem liệu lỗi bên dưới có phải là strconv.ErrRange hay strconv.ErrSyntax không.
sync
Mở khóa Mutex bị tranh chấp cao giờ nhường CPU trực tiếp cho goroutine tiếp theo đang chờ Mutex đó. Điều này cải thiện đáng kể hiệu năng của các mutex bị tranh chấp cao trên máy có nhiều CPU.
testing
Gói testing giờ hỗ trợ hàm cleanup, được gọi sau khi test hoặc benchmark kết thúc, bằng cách gọi T.Cleanup hoặc B.Cleanup tương ứng.
text/template
Gói text/template giờ báo cáo đúng lỗi khi đối số được đặt trong ngoặc đơn được dùng làm hàm. Điều này thường xuất hiện trong các trường hợp sai như {{if (eq .F "a") or (eq .F "b")}}. Nên viết là {{if or (eq .F "a") (eq .F "b")}}. Trường hợp sai chưa bao giờ hoạt động như mong đợi, và giờ sẽ được báo cáo với lỗi can't give argument to non-function.
JSEscape giờ thoát các ký tự & và = để giảm thiểu tác động của việc đầu ra của nó bị dùng sai trong các ngữ cảnh HTML.
unicode
Gói unicode và hỗ trợ liên quan trong toàn hệ thống đã được nâng cấp từ Unicode 11.0 lên Unicode 12.0, bổ sung 554 ký tự mới, bao gồm bốn script mới và 61 emoji mới.