1 điểm bởi GN⁺ 2025-02-16 | 3 bình luận | Chia sẻ qua WhatsApp
  • 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:wasmexport mớ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 add rồ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 export củ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
  • Khi dùng cùng runtime như Wazero, sau khi gọi _initialize có 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:wasmexport có 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àm go:wasmexport trả 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:wasmimportgo: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:wasmexport trong 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

 
click 2025-02-16

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.

 
xguru 2025-02-16

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.

 
GN⁺ 2025-02-16
Ý 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

    • Nếu muốn thử Go WASM trên Cloudflare Workers thì do kích thước tệp nhị phân nên cần phải đăng ký gói trả phí
    • Ở lần thử cuối cùng, hello-world chạy được nhưng những thứ phức tạp hơn thì vượt quá giới hạn kích thước
    • Thật đáng tiếc
  • Thật đáng ngạc nhiên. Điều cần ghi nhớ:

    • Công việc WebAssembly của Go không được thiết kế và triển khai bởi nhóm Go mà bởi các tình nguyện viên. Vì vậy tiến độ phụ thuộc vào thời gian rảnh của họ
  • 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ì

    • Sẽ rất hữu ích nếu có ai giải thích WASI mới đã cải thiện gì so với trước đây (ngoài việc hỗ trợ nhiều kiểu hơn qua FFI)
    • Câu hỏi thứ hai: trước đây có thể ép kiểu con trỏ sang số nguyên để lấy chuỗi và các kiểu phức tạp từ bộ nhớ instance của mô-đun WASM. Nếu biểu diễn nhị phân của kiểu của tôi trong Go được đảm bảo là ổn định, tôi tự hỏi liệu cách truyền con trỏ này vào mô-đun WASM được tạo khi dùng goos=wasip1 có còn hợp lệ hay không
  • Có 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

    • Điều này giống hệt cách export hiện có của cgo. Nó đi theo các ví dụ trước đó. Tính tiện dụng vẫn nằm ngoài ngôn 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

    • Các tiêu chuẩn phát triển chậm, và khi mức độ chấp nhận tăng lên thì sẽ có rủi ro phải hỗ trợ vĩnh viễn các tính năng phi tiêu chuẩn như WASI ngay cả về sau này nữa)