库
对于 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) 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
。
对包含未知变体的并集进行编码会写入未知数据和 重新连接到电线上。
在解码未知变体时,严格联合会失败。 在以下情况下,属于值类型的灵活联合会失败 使用句柄对未知变体进行解码。
表格
基于以下表定义:
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
常量,其中包含
协议名称。