库
对于 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 类型转换为原生 类型。这些类型可以在汇总类型中显示为成员,也可以显示为 传递给协议方法。
内置类型
系统会根据下表将 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 的可为 null 版本使用指针进行引用
更改为生成的类型:*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 位。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:返回此枚举值是否 未知。对于严格枚举,始终返回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: int_value int32;
2: string_value string:MAX_STRING_LENGTH;
};
FIDL 会生成别名和表示 union tag:
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:返回原始 未知数据的字节和句柄。句柄 Slice 在 遍历顺序,如果并集是空的,则该函数必须为空 一种资源类型。
FIDL 工具链还会生成用于构建实例的工厂函数
(共 JsonValue 个):
func JsonValueWithIntValue(intValue int32) JsonValuefunc 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。
对包含未知变体的并集进行编码会写入未知数据和 重新连接到电线上。
在解码未知变体时,严格联合会失败。 在以下情况下,属于值类型的灵活联合会失败 使用句柄对未知变体进行解码。
表格
基于以下表定义:
type User = table {
1: age uint8;
2: 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:返回 则使用指定的默认值。func (u *User) ClearAge()和func (u *User) ClearName():清除 字段。func (u *User) HasUnknownData() bool:检查是否存在任何未知 字段。func (u *User) GetUnknownData() map[uint64]fidl.UnknownData:返回地图 从序数到字节和句柄。标识名列表 按遍历顺序返回,如果存在以下情况,则保证为空 该表是 value 类型。
用法示例:
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 预留的名称
内嵌布局
协议
给定 protocol:
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 接口,在以下情况下,客户端会使用该接口:
以及由服务器代理调用服务器来实现协议:
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,绑定到另一端,代表客户端
end 的值。客户端和服务器部分对这些操作进行了说明
部分。
客户端
用于通过 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;Response,属于
TicTacToeMakeMoveResponse。
TicTacToeMakeMoveResponse 以包含字段的结构体的形式生成
对应成功响应的参数。在本示例中,它包含一个
单个 NewState 字段(类型为 GameState)。
协议组合
FIDL 没有继承的概念,它会生成完整的代码, (针对所有组合协议)执行上述操作。在 也就是
protocol A {
Foo();
};
protocol B {
compose A;
Bar();
};
提供与针对以下各项生成的代码相同的 API:
protocol A {
Foo();
};
protocol B {
Foo();
Bar();
};
除了方法序数之外,生成的代码完全相同。
协议和方法属性
过渡风格
为了在 Go 中支持 @transitional 属性,FIDL 生成了一个
TicTacToeWithCtxTransitionalBase 类型,该类型提供默认实现
每个标记为 @transitional 的方法。嵌入
TicTacToeWithCtxTransitionalBase将继续构建新的 Transitional
方法。
可检测到
标记为 @discoverable 时,生成的 InterfaceRequest 类型(在此例中)
示例 TicTacToeWithCtxInterfaceRequest)会实现 fidl.ServiceRequest,
这允许在服务发现中使用服务器端。
此外,FIDL 还会生成一个 TicTacToeName 常量,其中包含
协议名称。