- Các tính năng liên quan đến WebAssembly (Wasm) được mở rộng trong Go 1.24
- Directive
go:wasmexportđược bổ sung, cho phép gọi hàm Go từ bên ngoài mô-đun Wasm - Chế độ build “reactor” cho WASI cũng được hỗ trợ, cho phép chạy mã ở trạng thái hoạt động lâu dài
- Nhờ đó, mở ra khả năng mở rộng ứng dụng Go trong môi trường Wasm một cách linh hoạt hơn
WebAssembly and the WebAssembly System Interface
- WebAssembly là một định dạng nhị phân được tạo ra để chạy mã cấp thấp hiệu năng cao trong trình duyệt web
- Hiện nay, nó cũng được sử dụng rộng rãi ngoài trình duyệt, và có thể tương tác với tài nguyên hệ thống thông qua WebAssembly System Interface (WASI)
- Go bắt đầu hỗ trợ biên dịch sang Wasm từ phiên bản 1.11 thông qua cổng js/wasm, và ở phiên bản 1.21 đã bổ sung cổng mới nhắm tới API system call WASI preview 1 thông qua GOOS=wasip1
Export hàm Go thành Wasm bằng go:wasmexport
- Với directive
go:wasmexportmới được thêm trong Go 1.24, có thể công khai hàm Go dưới dạng export để có thể được gọi từ bên ngoài mô-đun Wasm - Ví dụ: khai báo như
//go:wasmexport addrồi viết hàm tương ứng, khi đó Wasm host có thể gọi hàm đó - Cách này tương tự directive
exportcủa cgo, nhưng được triển khai bằng cơ chế đơn giản hơn
Building a WASI Reactor
- WASI “reactor” là mô-đun WebAssembly hoạt động liên tục và có thể phản hồi sự kiện hoặc yêu cầu
- Trong Go 1.24, có thể build WASI reactor bằng tùy chọn
-buildmode=c-shared - Cờ build này chỉ thị cho linker không tạo hàm
_start(điểm vào của command module), mà thay vào đó tạo hàm_initialize- Reactor được khởi tạo thông qua hàm
_initialize, và hàm này phải được gọi trước thay vì hàm main
- Reactor được khởi tạo thông qua hàm
- Khi dùng cùng runtime như Wazero, sau khi gọi
_initializecó thể gọi lại các hàm đã export bao nhiêu lần tùy ý - Cách làm này hữu ích trong các môi trường sử dụng Wasm như cơ chế plugin hoặc mở rộng cho ứng dụng
Hỗ trợ kiểu dữ liệu phong phú giữa host và client
- Trong Go 1.24, các ràng buộc đối với kiểu tham số/kiểu trả về của các hàm được gọi bằng
go:wasmimportđã được nới lỏng - Ví dụ, có thể truyền bool, string, con trỏ int32, con trỏ struct, v.v.
- Tuy vậy, vẫn còn các giới hạn do khác biệt giữa môi trường 64-bit và 32-bit
- Điều này giúp việc viết ứng dụng Go Wasm trở nên tự nhiên và thuận tiện hơn, đồng thời loại bỏ các chuyển đổi kiểu không cần thiết
Hạn chế
- Wasm là kiến trúc đơn luồng, không có xử lý song song
- Hàm
go:wasmexportcó thể tạo goroutine mới, nhưng các hàm tạo goroutine nền sẽ không tiếp tục chạy sau khi hàmgo:wasmexporttrả về cho đến khi mô-đun Wasm dựa trên Go được gọi lại - Dù một số giới hạn kiểu dữ liệu đã được nới lỏng, vẫn còn các ràng buộc về những kiểu có thể dùng với hàm
go:wasmimportvàgo:wasmexport- Việc truyền kiểu phức hợp có chứa con trỏ vẫn còn hạn chế
Kết luận
- Việc bổ sung khả năng build WASI reactor và tính năng
go:wasmexporttrong Go 1.24 là cải tiến mở rộng đáng kể hệ sinh thái Wasm của Go - Nhờ đó, các nhà phát triển có thể tạo ra nhiều ứng dụng Wasm dựa trên Go đa dạng hơn, mở ra những khả năng mới cho Go trong hệ sinh thái Wasm
3 bình luận
Trước khi Wasm/gc được áp dụng rộng rãi, có lẽ sẽ tốt hơn nếu phát triển cho mục tiêu wasm bằng một ngôn ngữ không có gc.
Bản phát hành Go 1.24 chỉ giải thích ngắn gọn, nhưng đây là một bản cập nhật quan trọng hơn nhiều.
Ý kiến trên Hacker News
Có một vấn đề lớn là các tệp nhị phân WASM được tạo bằng Go rất lớn. TinyGo khắc phục được điều này, nhưng tốc độ biên dịch chậm và cần cẩn trọng khi chọn thư viện. Để vượt qua cả hai điểm này thì cần rất nhiều kiên nhẫn
hello-worldchạy được nhưng những thứ phức tạp hơn thì vượt quá giới hạn kích thướcThật đáng ngạc nhiên. Điều cần ghi nhớ:
Tôi không nhớ rõ trước Go 1.24 có thể xuất hàm Go sang JS hay chưa. Tôi nhớ là trước đây có thể gọi từ JS tới các hàm Go đã xuất mà không gặp vấn đề gì
goos=wasip1có còn hợp lệ hay khôngCó lẽ sẽ “đậm chất Go” hơn nếu xuất mọi hàm bắt đầu bằng chữ hoa trong gói main. Vì việc export vốn hoạt động như vậy trong ngôn ngữ này, nên chỉ nên dùng chỉ thị trình biên dịch khi cần chỉ định rõ những hàm bắt đầu bằng chữ thường
Không thấy đề cập gì đến việc làm việc với mô hình thành phần WASM
Tôi tự hỏi cơ chế gom rác của Go và WASM hoạt động như thế nào
Giá mà có một ngôn ngữ cấp thấp với kiểu dữ liệu mạnh và hỗ trợ WASM xuất sắc
Tôi tự hỏi làm sao để gỡ lỗi một mô-đun WASM đang chạy trong chương trình host
Tôi lo rằng việc khao khát có thêm nhiều tính năng WASM có thể làm tổn hại không thể đảo ngược tới hệ sinh thái còn non trẻ này. Phần lớn các tính năng mà Go bổ sung vào WASM vốn đã có thể được thực hiện theo cách native nếu đề xuất mô hình thành phần đã được hợp nhất