Giới thiệu
Bản phát hành Go phiên bản 1, gọi tắt là Go 1, là một cột mốc lớn trong quá trình phát triển của ngôn ngữ. Go 1 là một nền tảng ổn định cho sự phát triển của các chương trình và dự án viết bằng Go.
Go 1 định nghĩa hai thứ: thứ nhất, specification của ngôn ngữ; và thứ hai, specification của một tập các API lõi, tức các “standard package” của thư viện Go. Bản phát hành Go 1 bao gồm phần hiện thực của chúng dưới dạng hai bộ compiler (gc và gccgo), cùng bản thân các thư viện lõi.
Chủ đích là các chương trình viết theo specification của Go 1 sẽ tiếp tục biên dịch và chạy đúng, không cần sửa đổi, trong suốt vòng đời của specification đó. Vào một thời điểm chưa xác định, có thể sẽ xuất hiện specification cho Go 2, nhưng cho tới lúc đó, các chương trình Go chạy được hôm nay sẽ tiếp tục chạy được ngay cả khi có thêm các bản phát hành “point” tương lai của Go 1 (Go 1.1, Go 1.2, v.v.).
Tương thích ở mức mã nguồn. Tương thích ở mức binary cho các package đã biên dịch thì không được bảo đảm giữa các bản phát hành. Sau một bản phát hành point, mã nguồn Go sẽ cần được biên dịch lại để liên kết với bản phát hành mới.
Các API có thể lớn thêm, có thêm package và tính năng mới, nhưng không theo cách làm hỏng mã Go 1 hiện có.
Những gì có thể kỳ vọng
Mặc dù chúng tôi kỳ vọng rằng đại đa số chương trình sẽ giữ được tính tương thích này theo thời gian, không thể bảo đảm rằng không thay đổi nào trong tương lai sẽ làm hỏng bất kỳ chương trình nào. Tài liệu này là một nỗ lực nhằm xác lập kỳ vọng về tính tương thích của phần mềm Go 1 trong tương lai. Có một số cách mà một chương trình hôm nay biên dịch và chạy được lại có thể không còn như vậy sau một bản phát hành point trong tương lai. Tất cả đều khó xảy ra nhưng đáng được ghi lại.
- Bảo mật. Một vấn đề bảo mật trong specification hoặc trong phần hiện thực có thể lộ ra mà cách khắc phục đòi hỏi phá vỡ tính tương thích. Chúng tôi giữ quyền xử lý những vấn đề bảo mật như vậy.
- Hành vi không được đặc tả. Specification của Go cố gắng nói rõ về hầu hết các tính chất của ngôn ngữ, nhưng có một số khía cạnh không được định nghĩa. Các chương trình phụ thuộc vào những hành vi không được đặc tả đó có thể hỏng trong các bản phát hành tương lai.
- Lỗi trong specification. Nếu cần phải xử lý một điểm không nhất quán hoặc thiếu sót trong specification, việc giải quyết vấn đề đó có thể ảnh hưởng tới ý nghĩa hoặc tính hợp lệ của các chương trình hiện có. Chúng tôi giữ quyền xử lý những vấn đề như vậy, kể cả việc cập nhật các phần hiện thực. Ngoại trừ các vấn đề bảo mật, sẽ không có thay đổi nào không tương thích được thực hiện với specification.
- Lỗi. Nếu một compiler hoặc thư viện có lỗi vi phạm specification, một chương trình phụ thuộc vào hành vi lỗi đó có thể hỏng khi lỗi được sửa. Chúng tôi giữ quyền sửa những lỗi như vậy.
- Struct literal. Để bổ sung tính năng trong các bản phát hành point về sau, có thể cần thêm trường vào các struct được export trong API. Mã dùng struct literal không có khoá (chẳng hạn pkg.T{3, “x”}) để tạo giá trị thuộc những kiểu này sẽ không biên dịch được sau một thay đổi như vậy. Tuy nhiên, mã dùng literal có khoá (pkg.T{A: 3, B: “x”}) sẽ tiếp tục biên dịch được sau thay đổi đó. Chúng tôi sẽ cập nhật những cấu trúc dữ liệu như vậy theo cách cho phép struct literal có khoá vẫn tương thích, dù literal không có khoá có thể không biên dịch được. (Cũng có những trường hợp rắc rối hơn liên quan tới cấu trúc dữ liệu lồng nhau hoặc interface, nhưng cách giải quyết vẫn thế.) Vì vậy chúng tôi khuyến nghị rằng các composite literal có kiểu được định nghĩa trong một package khác thì nên dùng ký pháp có khoá.
- Method. Cũng như với trường của struct, có thể cần thêm method vào các kiểu không phải interface. Trong một số trường hợp, chẳng hạn khi kiểu đó được embed vào một struct cùng với một kiểu khác, việc thêm method mới có thể làm hỏng struct đó do tạo ra xung đột với một method sẵn có của kiểu được embed kia. Chúng tôi không thể phòng ngừa trường hợp hiếm gặp này và không bảo đảm tính tương thích nếu nó xảy ra.
- Dot import. Nếu một chương trình import một standard package bằng
import . "path", những tên được định nghĩa thêm trong package được import ở các bản phát hành tương lai có thể xung đột với các tên khác được định nghĩa trong chương trình. Chúng tôi không khuyến nghị dùngimport .ngoài phạm vi test, và việc dùng nó có thể khiến một chương trình không biên dịch được ở các bản phát hành tương lai. - Việc dùng package
unsafe. Các package importunsafecó thể phụ thuộc vào các tính chất nội bộ của phần hiện thực Go. Chúng tôi giữ quyền thực hiện những thay đổi trong phần hiện thực có thể làm hỏng những chương trình như vậy.
Dĩ nhiên, với tất cả những khả năng đó, nếu chúng xảy ra, chúng tôi sẽ nỗ lực hết sức khi khả thi để cập nhật specification, compiler hoặc thư viện mà không ảnh hưởng tới mã hiện có.
Chính những cân nhắc này cũng áp dụng cho các bản phát hành point kế tiếp nhau. Ví dụ, mã chạy được dưới Go 1.2 sẽ tương thích với Go 1.2.1, Go 1.3, Go 1.4, v.v., dù không nhất thiết tương thích với Go 1.1 vì nó có thể dùng những tính năng chỉ được thêm vào ở Go 1.2
Các tính năng được thêm vào giữa các bản phát hành, có sẵn trong repository mã nguồn nhưng chưa thuộc các bản phát hành binary có đánh số, là đang trong quá trình phát triển tích cực. Không có cam kết tương thích nào cho phần mềm dùng những tính năng đó cho tới khi chúng được phát hành.
Cuối cùng, dù đây không phải vấn đề về tính đúng đắn, có khả năng hiệu năng của một chương trình bị ảnh hưởng bởi những thay đổi trong phần hiện thực của các compiler hoặc thư viện mà nó phụ thuộc vào. Không thể bảo đảm điều gì về hiệu năng của một chương trình cụ thể giữa các bản phát hành.
Dù những kỳ vọng này áp dụng cho chính Go 1, chúng tôi hy vọng những cân nhắc tương tự cũng sẽ được áp dụng cho việc phát triển phần mềm bên ngoài xây dựng trên nền Go 1.
Các sub-repository
Mã trong các sub-repository của cây go chính, chẳng hạn golang.org/x/net, có thể được phát triển theo những yêu cầu tương thích lỏng hơn. Tuy nhiên, các sub-repository sẽ được gắn tag phù hợp để nhận diện những phiên bản tương thích với các bản phát hành point của Go 1.
Hệ điều hành
Không thể bảo đảm tương thích dài hạn với các giao diện của hệ điều hành, vốn bị thay đổi bởi các bên bên ngoài. Do đó package syscall nằm ngoài phạm vi các bảo đảm nêu ở đây. Kể từ Go phiên bản 1.4, package syscall bị đóng băng. Mọi tiến hoá của giao diện system call phải được hỗ trợ ở nơi khác, chẳng hạn trong subrepository go.sys. Để biết chi tiết và bối cảnh, xem tài liệu này.
Công cụ
Cuối cùng, toolchain của Go (compiler, linker, công cụ build, v.v.) đang trong quá trình phát triển tích cực và có thể thay đổi hành vi. Điều này nghĩa là, chẳng hạn, các script phụ thuộc vào vị trí và tính chất của các công cụ có thể bị hỏng bởi một bản phát hành point.
Bỏ qua những lưu ý đó, chúng tôi tin rằng Go 1 sẽ là một nền tảng vững chắc cho sự phát triển của Go và hệ sinh thái của nó.