程式庫
根據 library
宣告:
library fuchsia.examples;
系統會產生 examples
Go 套件中的繫結程式碼,並擷取 FIDL 程式庫名稱的最後一個元件來取得此套件。
您可使用 路徑匯入套件:
import "fidl/fuchsia/examples"
常數
常數會以 const
區塊的形式產生。例如,下列常數:
const BOARD_SIZE uint8 = 9;
const NAME string = "Tic-Tac-Toe";
產生的公式為:
const (
BoardSize uint8 = 9
Name string = "Tic-Tac-Toe"
)
FIDL 原始類型和 Go 類型之間的對應列於內建類型中。
欄位
本節說明 FIDL 工具鍊如何將 FIDL 類型轉換為 Go 中的原生類型。這些類型可以顯示為匯總類型的成員,或做為通訊協定方法的參數。
內建類型
系統會根據下表將 FIDL 類型轉換為 Go 類型。
FIDL 類型 | Go 類型 |
---|---|
bool |
bool |
int8 |
int8 |
int16 |
int16 |
int32 |
int32 |
int64 |
int64 |
uint8 |
uint8 |
uint16 |
uint16 |
uint32 |
uint32 |
uint64 |
uint64 |
float32 |
float32 |
float64 |
float64 |
array<T, N> |
[N]T |
vector<T>:N |
[]T |
vector<T>:N? |
*[]T |
string |
string |
string:optional |
*string |
server_end:P |
產生的伺服器結束類型 PInterfaceRequest ,請參閱「通訊協定」 |
client_end:P |
產生的用戶端結束類型 PInterface ,請參閱「通訊協定」 |
zx.Handle:S ,zx.Handle:<S, optional> |
如果 Go 執行階段支援,則會使用對等的帳號代碼類型 (例如 zx.VMO 、zx.Channel 和 zx.Event )。否則,系統會使用 zx.Handle |
zx.Handle ,zx.Handle:optional |
zx.Handle |
使用者定義的類型
在 Go 中,使用者定義的類型 (位元、列舉、常數、結構、聯集或資料表) 是指使用產生的類型 (請參閱「類型定義」)。使用者定義類型 T
的可為空值版本參照產生的類型為 *T
。
類型定義
請注意,在本節中,系統產生的 Go 程式碼並非呈現 FIDL 產生的確切程式碼。例如,產生的結構體可能包含未匯出的欄位,而這些欄位無法使用反射進行檢查。
點數
根據 bits 定義:
const BOARD_SIZE uint8 = 9;
const NAME string = "Tic-Tac-Toe";
FIDL 會產生基礎類型 (如果未指定,則為 uint32
) 的類型別名以及每個位元成員的常數:
type FileMode uint16
const (
FileModeRead FileMode = 1
FileModeWrite FileMode = 2
FileModeExecute FileMode = 4
FileMode_Mask FileMode = 7
)
FileMode_Mask
值是位元遮罩,包含 FIDL 結構定義中定義的每個位元成員。
此外,還提供下列 FileMode
方法:
func (x FileMode) String() string
:傳回使用者可理解的位元字串。func (x FileMode) GetUnknownBits() uint64
:以uint64
的形式傳回只包含此位元值中的未知成員值。一律針對 strict 位元傳回 0。func (x FileMode) HasUnknownBits() bool
:傳回這個值是否包含任何未知的位元。針對嚴格位元一律傳回false
。func (x FileMode) InvertBits() FileMode
:反轉所有已知的位元。所有未知的位元都會設為 false。func (x FileMode) ClearBits(mask FileMode) FileMode
:修改位元欄位,取消設定遮罩中的所有位元。func (x FileMode) HasBits(mask FileMode) bool
:驗證遮罩中的所有翻轉位元都已設定完成。
使用範例:
func ExampleFileMode() {
fmt.Println(examples.FileModeRead.String())
fmt.Println(examples.FileModeWrite | examples.FileModeExecute)
// Output:
// Read
// Write|Execute
}
列舉
根據 enum 定義:
type LocationType = strict enum {
MUSEUM = 1;
AIRPORT = 2;
RESTAURANT = 3;
};
FIDL 會產生基礎類型 (如果未指定,則為 uint32
) 的類型別名和每個列舉成員的常數:
type LocationType uint32
const (
LocationTypeMuseum LocationType = 1
LocationTypeAirport LocationType = 2
LocationTypeRestaurant LocationType = 3
)
如果 LocationType
是「彈性」,也會有未知的預留位置成員:
LocationType_Unknown LocationType = 0x7fffffff
如果列舉中有成員標記了 [Unknown]
屬性,則產生的不明變數值會與已標記的不明成員相同。
LocationType
提供以下方法:
func (x LocationType) IsUnknown() bool
:傳回這個列舉值是否為未知值。如果是 strict 列舉,一律會傳回false
。func (x LocationType) String() string
:傳回人類可讀的列舉字串。
使用範例:
func ExampleLocationType() {
fmt.Println(examples.LocationTypeMuseum.String())
// Output: Museum
}
結構
如果是 struct 宣告:
type Color = struct {
id uint32;
@allow_deprecated_struct_defaults
name string:MAX_STRING_LENGTH = "red";
};
FIDL 工具鍊會產生具有相符欄位的 Color
結構:
type Color struct {
Id uint32
Name string
}
Go 繫結目前不支援結構欄位的預設值。
使用範例:
func ExampleColor() {
red := examples.Color{Id: 1, Name: "ruby"}
fmt.Println(red.Id)
fmt.Println(red.Name)
// Output:
// 1
// ruby
}
聯盟
根據聯集定義:
type JsonValue = strict union {
1: reserved;
2: int_value int32;
3: string_value string:MAX_STRING_LENGTH;
};
FIDL 會產生代表聯集標記的別名和相關常數:
type I_jsonValueTag uint64
const (
JsonValueIntValue = 2
JsonValueStringValue = 3
)
以及含有標記欄位和聯集每個變化版本的 JsonValue
結構:
type JsonValue struct {
I_jsonValueTag
IntValue int32
StringValue string
}
JsonValue
提供以下方法:
func (_m *JsonValue) Which() I_jsonValueTag
:傳回聯集標記。func (_m *JsonValue) SetIntValue(intValue int32)
和func (_m *JsonValue) SetStringValue(stringValue string)
:將聯集設為包含特定變化版本,並據此更新標記。
如果 JsonValue
是「彈性」,就會包含下列其他方法:
func (_m *JsonValue) GetUnknownData() fidl.UnknownData
:傳回未知資料的原始位元組和控點。控點片段會按照遍歷順序傳回,如果聯集是資源類型,則處理方保證為空白。
FIDL 工具鍊也會產生工廠函式來建構 JsonValue
的例項:
func JsonValueWithIntValue(intValue int32) JsonValue
func JsonValueWithStringValue(stringValue string) JsonValue
使用範例:
func ExampleJsonValue() {
val := examples.JsonValueWithStringValue("hi")
fmt.Println(val.Which() == examples.JsonValueStringValue)
fmt.Println(val.StringValue)
val.SetIntValue(1)
fmt.Println(val.Which() == examples.JsonValueIntValue)
fmt.Println(val.IntValue)
// Output:
// true
// hi
// true
// 1
}
彈性聯集和未知變體
彈性聯集在產生的標記類別中具有額外變數:
const (
JsonValue_unknownData = 0
// other tags omitted...
)
如果 FIDL 訊息包含有不明變化版本的聯集,解碼為 JsonValue
時,.Which()
會傳回 JsonValue_unknownData
。
為含有不明變體的聯集編碼會將未知的資料,將原始序數寫回線路。
解碼不明變化版本時,Strict 聯集會失敗。使用帳號代碼解碼不明變數時,值類型的彈性聯集會失敗。
桌子
以下列資料表定義為例:
type User = table {
1: reserved;
2: age uint8;
3: name string:MAX_STRING_LENGTH;
};
FIDL 工具鍊會產生 User
結構,該結構會針對每個欄位提供存在欄位:
type User struct {
Age uint8
AgePresent bool
Name string
NamePresent bool
}
User
提供以下方法:
func (u *User) HasAge() bool
和func (u *User) HasName() bool
:檢查欄位是否存在。func (u *User) SetAge(age uint8)
和func (u *User) SetName(name string)
:欄位 setter。func (u *User) GetAge() uint8
和func (u *User) GetName() string
:欄位 getter。func (u *User) GetAgeWithDefault(_default uint8) uint8
和func (u *User) GetNameWithDefault(_default string) string
:欄位 getter,如果不存在,就會傳回指定的預設值。func (u *User) ClearAge()
和func (u *User) ClearName()
:清除欄位的存在。func (u *User) HasUnknownData() bool
:檢查是否有任何未知欄位。func (u *User) GetUnknownData() map[uint64]fidl.UnknownData
:傳回位元組對位元組的對應,並處理任何不明欄位。帳號代碼清單會按照遍歷順序傳回;如果資料表是值類型,則字串保證為空白。
使用範例:
func ExampleUser() {
var user examples.User
fmt.Println(user.HasAge(), user.HasName())
user.SetAge(30)
user.SetName("John")
fmt.Println(user.GetAge(), user.GetName())
user.ClearAge()
user.ClearName()
fmt.Println(user.HasAge(), user.HasName())
fmt.Println(user.GetNameWithDefault("Unknown"))
// Output:
// false false
// 30 John
// false false
// Unknown
}
內嵌版面配置
產生的 Go 程式碼會使用 fidlc
保留的名稱做為內嵌版面配置。
通訊協定
closed protocol TicTacToe {
strict StartGame(struct {
start_first bool;
});
strict MakeMove(struct {
row uint8;
col uint8;
}) -> (struct {
success bool;
new_state box<GameState>;
});
strict -> OnOpponentMove(struct {
new_state GameState;
});
};
FIDL 會產生 TicTacToeWithCtx
介面,用戶端會在 Proxy 呼叫伺服器時使用,以及伺服器實作通訊協定:
type TicTacToeWithCtx interface {
StartGame(ctx_ fidl.Context, startFirst bool) error
MakeMove(ctx_ fidl.Context, row uint8, col uint8) (bool, *GameState, error)
}
每個方法都會使用 Context
做為第一個引數,後面接著要求參數。觸發和清除方法會傳回 error
;兩種方式會傳回回應參數,後面接著 error
。
與 TicTacToe
通訊協定互動的進入點為下列函式:
func NewTicTacToeWithCtxInterfaceRequest() (TicTacToeWithCtxInterfaceRequest, *TicTacToeWithCtxInterface, error)
這個函式會建立管道,並傳回繫結至管道的一端的 TicTacToeWithCtxInterfaceRequest
(代表伺服器結束),以及繫結至另一端 (代表用戶端) 的 TicTacToeWithCtxInterface
。相關說明請參閱「用戶端」和「伺服器」一節。
用戶端
用來透過 TicTacToe
通訊協定通訊的管道端為 TicTacToeWithCtxInterface
。實作了通訊協定中所述的 TicTacToeWithCtx
介面,以及處理事件的方法。請注意,在這個實作項目中,兩個方法呼叫會同步並封鎖,直到收到回應為止。
如需 Go FIDL 用戶端的範例,請參閱 //examples/fidl/go/client。
伺服器
為這個 FIDL 通訊協定實作伺服器時,需要提供 TicTacToeWithCtx
介面的具體實作。
繫結會產生 TicTacToeWithCtxInterfaceRequest
類型,用來代表透過 TicTacToe
通訊協定進行通訊的管道端伺服器。提供了以下方法:
func (c EchoWithCtxInterfaceRequest) ToChannel() zx.Channel
:將介面要求轉換回未輸入類型的管道。
如需 Go FIDL 伺服器的範例,請參閱 //examples/fidl/go/server。
事件
用戶端
TicTacToeWithCtxInterface
提供處理事件的方法:
func (p *TicTacToeWithCtxInterface) ExpectOnOpponentMove(ctx_ fidl.Context) (GameState, error)
:OnOppponentMove
的事件處理常式,該處理常式使用Context
並傳回事件參數。
呼叫任何事件處理常式方法將讀取下一個緩衝事件或區塊,直到收到該事件或區塊為止,呼叫端應及時排除事件緩衝區,避免 FIDL 繫結中發生不受限的緩衝情況。如果下一個事件與呼叫的方法相符,系統就會傳回該事件的參數。否則系統會傳回錯誤。用戶端必須自行確保接收事件的順序與處理事件的順序相符。
伺服器
伺服器可以使用 TicTacToeEventProxy
傳送事件,為通訊協定中的每個事件提供方法:
func (p *TicTacToeEventProxy) OnOpponentMove(newState GameState) error
:傳送OnOpponentMove
事件。
建立 TicTacToeEventProxy
需要存取用戶端的管道。Go 伺服器範例說明如何在伺服器端取得 EventProxy
。
成果
Go 繫結不會對含有錯誤類型的方法有任何特殊處理。
假設方法含有錯誤類型:
protocol TicTacToe {
MakeMove(struct {
row uint8;
col uint8;
}) -> (struct {
new_state GameState;
}) error MoveError;
};
TicTacToeWithCtx
介面上 MakeMove
的方法簽章如下:
MakeMove(ctx_ fidl.Context, row uint8, col uint8) (TicTacToeMakeMoveResult, error)
TicTacToeMakeMoveResult
會產生為包含兩個變化版本的聯集:Err
,MoveError
為 MoveError
,Response
,則為 TicTacToeMakeMoveResponse
。
TicTacToeMakeMoveResponse
會產生為 struct,其中包含對應成功回應參數的欄位。在本例中,包含 GameState
類型的單一 NewState
欄位。
通訊協定組成
FIDL 沒有繼承的概念,而是針對所有組合的通訊協定產生上述完整程式碼。換句話說,產生的程式碼
protocol A {
Foo();
};
protocol B {
compose A;
Bar();
};
為下列項目提供與程式碼產生相同的 API:
protocol A {
Foo();
};
protocol B {
Foo();
Bar();
};
除了方法序數之外,產生的程式碼皆相同。
通訊協定和方法屬性
過渡
為了支援 Go 中的 @transitional
屬性,FIDL 會產生 TicTacToeWithCtxTransitionalBase
類型,為所有標示為 @transitional
的方法提供預設實作。嵌入 TicTacToeWithCtxTransitionalBase
的伺服器實作會繼續新增一個轉換方法。
可供偵測
標示為 @discoverable
時,產生的 InterfaceRequest
類型 (在此範例中為 TicTacToeWithCtxInterfaceRequest
) 會實作 fidl.ServiceRequest
,以便讓伺服器端在服務探索中使用。
此外,FIDL 會產生包含通訊協定名稱的 TicTacToeName
常數。