Trong Go 1 - xèng

Ngày 05 tháng 10 năm 2019 - Máy tính

Go 1.11 đã được phát hành đúng hẹn sau nửa năm kể từ phiên bản Go 1.10. Phần lớn những thay đổi tập trung vào việc cải tiến công cụ, thời gian chạy và thư viện. Phiên bản này tiếp tục tuân thủ nguyên tắc tương thích của Go 1, với kỳ vọng hầu hết các chương trình sẽ biên dịch và hoạt động như trước đây.

1. Cải tiến trong phần cấy

  • ty le bd Hỗ trợ WebAssembly: Trong Go 1.11, có sự hỗ trợ thử nghiệm cho WebAssembly (js/wasm). Hiện tại, một chương trình Go khi biên dịch thành mô-đun WebAssembly sẽ bao gồm runtime Go với khả năng điều độ goroutine, bộ thu rác, cũng như các cấu trúc dữ liệu như map. Điều này khiến kích thước tệp nhị phân đích nhỏ nhất đạt khoảng 2MB (khoảng 500KB khi nén). Các chương trình Go có thể sử dụng gói thử nghiệm syscall/js để gọi JavaScript. Việc tối ưu hóa kích thước tệp nhị phân và tương tác với ngôn ngữ khác chưa nằm trong danh sách ưu tiên, nhưng có thể sẽ được giải quyết trong các phiên bản sau.

Tất cả các giá trị mới thêm vào biến môi trường GOOS là "js" và GOARCH là "wasm". Các file go có tên kết thúc bằng *_js.go hoặc *_wasm.go sẽ bị công cụ Go bỏ qua (trừ khi GOOS/GOARCH được thiết lập phù hợp). Nếu chương trình hiện tại chứa các file thỏa mãn cách đặt nạp tiền bằng thẻ game w88 tên này, cần phải đổi tên chúng.

Để biết thêm về việc sử dụng Go với WebAssembly, xem "Khám phá Go WebAssembly".

2. Cải tiến công cụ

  • Hỗ trợ mô-đun và quản lý phiên bản gói: Go 1.11 giới thiệu hỗ trợ sơ bộ cho mô-đun. Với mô-đun, nhà phát triển không còn bị ràng buộc vào GOPATH, thông tin phụ thuộc phiên bản rõ ràng hơn và nhẹ nhàng hơn, giúp quá trình xây dựng đáng tin cậy và dễ tái tạo hơn. Chi tiết xem tại "Golang Modules".

  • Giới hạn đường dẫn tham chiếu: Do sự hỗ trợ mô-đun, ký tự '@' trong các lệnh dòng lệnh giờ đây có ý nghĩa đặc biệt. Vì vậy, các lệnh go hiện không cho phép sử dụng ký tự '@' trong đường dẫn tham chiếu. Hạn chế này chỉ ảnh hưởng đến các build tùy chỉnh.

  • Tải gói mới: Gói mới golang.org/x/tools/go/packages cung cấp một API đơn giản để định vị và tải các gói mã nguồn. Mặc dù không phải là một phần của thư viện chuẩn, nó đã trở thành lựa chọn hiệu quả thay thế cho gói go/build (API này không hỗ trợ đầy đủ mô-đun). Bằng cách chạy các lệnh truy vấn bổ sung như go list để lấy thông tin gói, việc xây dựng công cụ phân tích và làm việc cùng các hệ thống xây dựng tùy chọn như Bazel và Buck trở nên tốt hơn.

  • Bộ nhớ đệm xây dựng: Go 1.11 sẽ là phiên bản cuối cùng hỗ trợ việc đặt biến môi trường GOCACHE=off (bỏ qua bộ nhớ đệm xây dựng, được giới thiệu từ Go 1.10). Từ Go 1.12, bộ nhớ đệm xây dựng sẽ là bắt buộc, như một phần của quá trình loại bỏ $GOPATH/pkg. Hỗ trợ mô-đun và tải gói yêu cầu bộ nhớ đệm phải được bật.

  • Công cụ chuỗi công cụ biên dịch: Hiện tại, nhiều hàm hơn được ưu tiên nội suy theo mặc định, bao gồm các hàm gọi panic.

Công cụ chuỗi công cụ biên dịch hiện hỗ trợ thông tin cột cho nguyên thủy dòng.

Một định dạng dữ liệu xuất khẩu gói mới đã được giới thiệu. Ngoài việc tăng tốc độ xây dựng cho các dự án Go lớn, nó vẫn sẽ là minh bạch đối với người dùng cuối. Nếu gặp vấn đề, bạn có thể tắt tính năng này bằng cách truyền gcflags=all=-iexport=false khi sử dụng go tool để xây dựng tệp nhị phân.

Công cụ biên dịch hiện cấm các khai báo biến không sử dụng trong câu lệnh chọn kiểu. Ví dụ: biến x trong đoạn mã dưới đây:

1func f(v interface{}) {
2    switch x := v.(type) {
3    }
4}
  • Gỡ lỗi: Công cụ biên dịch hiện tạo thông tin gỡ lỗi chính xác hơn cho các tệp nhị phân đã tối ưu hóa, bao gồm thông tin vị trí biến, số dòng và vị trí điểm dừng. Điều này có thể được sử dụng để gỡ lỗi các tệp nhị phân không được biên dịch với -N -l. Chất lượng thông tin gỡ lỗi vẫn còn hạn chế và sẽ được cải thiện trong các phiên bản sau.

Do thông tin gỡ lỗi mở rộng và chính xác hơn, phần DWARF hiện được nén theo mặc định. Điều này là minh bạch đối với hầu hết các công cụ ELF (như các trình gỡ lỗi trên Linux và *BSD) và được hỗ trợ bởi trình gỡ lỗi Delve trên tất cả các nền tảng, nhưng hỗ trợ từ các công cụ gốc trên macOS và Windows còn hạn chế. Để hủy nén DWARF, bạn có thể truyền -ldflags=-compressdwarf=false khi sử dụng go tool để xây dựng tệp nhị phân.

Go 1.11 cung cấp hỗ trợ thử nghiệm cho việc gọi các hàm Go từ bên trong trình gỡ lỗi. Điều này rất hữu ích, ví dụ như khi dừng ở một điểm dừng và muốn gọi phương thức String. Tính năng này hiện chỉ hỗ trợ Delve phiên bản 1.1.0 trở lên.

  • Kiểm tra: Kể từ Go 1.10, lệnh go test sẽ chạy go vet trên gói đang được kiểm tra để phát hiện các vấn đề trước khi kiểm tra. Vì vet thực hiện kiểm tra kiểu trước khi chạy, các trường hợp kiểm tra không vượt qua kiểm tra kiểu sẽ thất bại. Đặc biệt, các trường hợp có biến không sử dụng trong closure mà đã được chấp nhận bởi trình biên dịch Go 1.10 hiện sẽ thất bại.

Lệnh -memprofile trong go test hiện có giá trị mặc định là "allocs", ghi lại tổng số byte đã cấp phát kể từ khi bắt đầu kiểm tra (bao gồm byte từ bộ thu rác).

  • Vet: Khi gói đang được phân tích không vượt qua kiểm tra kiểu, go vet sẽ trả về lỗi nghiêm trọng (trước đây chỉ in ra cảnh báo).

Ngoài ra, go vet có kiểm tra mạnh mẽ hơn đối với định dạng printf. Ví dụ, đoạn mã dưới đây sẽ gây lỗi:

1// test.go
2func wrapper(s string, args ...interface{}) {
3    fmt.Printf(s, args...)
4}
5func main() {
6    wrapper("%s", 42)
7}
1$ go vet test.go
2# command-line-arguments
3./test.go:10:2: wrapper format %s has arg 42 of wrong type int
  • Trace: Người dùng có thể ghi thông tin ứng dụng cấp độ trace bằng cách sử dụng API người dùng mới từ gói runtime/trace, cũng như nhóm các goroutine liên quan. go tool trace có thể trực quan hóa các thông tin này.

  • Cgo: Từ Go 1.10, cgo đã chuyển đổi một số kiểu con trỏ C thành kiểu uintptr Go. Những kiểu này bao gồm CFTypeRef từ khung lõi Darwin và jobject từ giao diện JNI của Java. Trong Go 1.11, đã có nhiều cải tiến để phát hiện các kiểu này. Mã sử dụng các kiểu này có thể cần cập nhật.

  • Lệnh Go: Biến môi trường GOFLAGS hiện có thể được sử dụng để đặt các cờ mặc định cho lệnh go. Điều này rất hữu ích trong một số tình huống. Trên các hệ thống nơi liên kết chậm do DWARF, người dùng có thể đặt -ldflags=-w theo mặc định. Đối với mô-đun, người dùng hoặc hệ thống tích hợp liên tục có thể đặt -mod=vendor theo mặc định nếu muốn sử dụng chế độ vendor.

  • Godoc: Go 1.11 sẽ là phiên bản cuối cùng hỗ trợ lệnh godoc. Trong các phiên bản tương lai, godoc sẽ chỉ là một dịch vụ web, và người dùng có thể sử dụng go doc làm công cụ giúp đỡ dòng lệnh.

  • Chạy: Lệnh go run hiện cho phép truyền một đường dẫn duy nhất, tên thư mục hoặc mẫu khớp với gói. Điều này cho phép go run pkg hoặc go run dir, thậm chí go run ..

3. Thời gian chạy

Hiện tại, thời gian chạy sử dụng bố cục đống thưa thớt, vì vậy không còn giới hạn kích thước đống Go (trước đây giới hạn ở mức 512GiB). Điều này sửa chữa các trường hợp hiếm khi xảy ra "xung đột không gian địa chỉ" (ví dụ trong các tệp nhị phân hỗn hợp Go/C hoặc khi sử dụng -race để biên dịch).

Trên hệ thống macOS và iOS, thời gian chạy hiện sử dụng libSystem.dylib thay vì gọi trực tiếp vào nhân. Điều này sẽ giúp các tệp nhị phân Go tương thích hơn với các phiên bản macOS và iOS trong tương lai. Gói syscall vẫn sử dụng các cuộc gọi hệ thống trực tiếp và kế hoạch sửa chữa trong tương lai.

4. Hiệu suất

Gói math/big có nhiều cải tiến về hiệu suất, cũng như có nhiều cải tiến về hiệu suất cho GOARCH=arm64.

  • Công cụ chuỗi công cụ biên dịch: Bộ biên dịch hiện tối ưu hóa việc dọn dẹp map theo cách sau:
1for k := range m {
2    delete(m, k)
3}

Ngoài ra, bộ biên dịch cũng tối ưu hóa việc mở rộng slice theo cách sau:

1append(s, make([]T, n)...)

Bộ biên dịch hiện hoạt động tốt hơn trong việc kiểm tra ranh giới và loại bỏ nhánh. Nó hiện nhận diện các mối liên hệ chuyển tiếp, ví dụ: nếu i < j và j < len(s), thì nó sẽ sử dụng sự kiện này để bỏ qua kiểm tra s[i]. Nó cũng hiểu một chút về phép toán đơn giản như s[i-10], từ đó nhận diện nhiều trường hợp quy nạp hơn trong vòng lặp. Hơn nữa, bộ biên dịch hiện sử dụng thông tin ranh giới để tối ưu hóa tích cực hơn các phép dịch.