Go Interface: iface and eface
iface
và eface
là hai cấu trúc dữ liệu cơ bản trong Go để mô tả các giao diện. Sự khác biệt giữa chúng là iface
mô tả giao diện chứa các phương thức, trong khi eface
là một giao diện trống không chứa bất kỳ phương thức nào: interface{}
.
Xem mã nguồn:
iface
duy trì hai con trỏ bên trong, tab
trỏ đến một thực thể itab
, nó đại diện cho kiểu của giao diện và kiểu thực thể được gán cho giao diện này. data
trỏ đến giá trị cụ thể của giao diện, thường là một con trỏ đến bộ nhớ heap.
Hãy xem kỹ cấu trúc itab
: Trường _type
mô tả kiểu thực thể, bao gồm cách căn chỉnh bộ nhớ, kích thước, v.v. Trường inter
mô tả kiểu giao diện. Trường fun
chứa địa chỉ của các phương thức tương ứng với kiểu dữ liệu cụ thể, thực hiện việc phân phối động của phương thức gọi giao diện. Thông thường, bảng này sẽ được cập nhật mỗi khi gán một giá trị cho giao diện hoặc lấy bảng itab từ bộ nhớ cache.
Ở đây chỉ liệt kê các phương thức liên quan đến kiểu thực thể và giao diện, các phương thức khác của kiểu thực thể không xuất hiện ở đây. Nếu bạn đã học qua C++, bạn có thể so sánh với khái niệm hàm ảo.
Ngoài ra, bạn có thể thấy lạ, tại sao mảng fun
có kích thước là 1, nếu giao diện có nhiều phương thức thì sao? Thực tế, đây là địa chỉ của phương thức đầu tiên, nếu có nhiều phương thức, chúng sẽ được lưu trữ trong không gian bộ nhớ sau đó. Từ góc nhìn của hợp ngữ, bạn có thể truy cập các con trỏ hàm này bằng cách tăng địa chỉ, không có ảnh hưởng gì. Lưu ý rằng các phương thức này được sắp xếp theo thứ tự từ điển của tên hàm.
Hãy xem tổng quan cấu trúc iface
trong sơ đồ sau:
Tiếp theo, hãy xem mã nguồn của eface
:
So với iface
, eface
đơn giản hơn. Nó chỉ duy trì một trường _type
, đại diện cho kiểu thực thể mà giao diện trống này chứa. data
mô tả giá trị cụ thể.
Chúng ta hãy xem một ví dụ:
Chạy lệnh sau để in ra hợp ngữ:
Chúng ta có thể thấy rằng hai hàm được gọi trong hàm main
:
Các tham số của hai hàm này có thể liên quan đến các trường của cấu trúc iface
và eface
: cả hai hàm “tạo” các tham số để tạo thành giao diện cuối cùng.
Như một bổ sung, hãy xem cấu trúc _type
:
Các loại dữ liệu khác nhau trong Go được quản lý dựa trên trường _type
, với các trường bổ sung để quản lý:
Các định nghĩa cấu trúc này của các loại dữ liệu là cơ sở cho việc triển khai phản chiếu (reflect).