Given the library
declaration:
library games.tictactoe;
Bindings code is generated into a tictactoe
Go package, which is obtained by taking the last component of the FIDL library name.
The package can be imported using the path:
import tictactoe "fidl/games/tictactoe"
Constants are generated as a const
block. For example, the following constants:
const uint8 BOARD_SIZE = 9; const string NAME = "Tic-Tac-Toe";
Are generated as:
const ( BoardSize uint8 = 9 Name string = "Tic-Tac-Toe" )
The correspondence between FIDL primitive types and Go types is outlined in built-in types.
This section describes how the FIDL toolchain converts FIDL types to native types in Go. These types can appear as members in an aggregate type or as parameters to a protocol method.
The FIDL types are converted to Go types based on the following table.
FIDL Type | Go Type |
---|---|
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? | *string |
request<P> | The generated server end type PInterfaceRequest , see Protocols |
P | The generated client end type PInterface , see Protocols |
handle<S> ,handle<S>? | The equivalent handle type is used if it is supported by the Go runtime (e.g. zx.VMO , zx.Channel , and zx.Event ). Otherwise, zx.Handle is used |
handle ,handle? | zx.Handle |
In Go, a user defined type (bits, enum, constant, struct, union, or table) is referred to using the generated type (see Type Definitions). The nullable version of a user defined type T
is referred to using a pointer to the generated type: *T
.
Note that in this section, the example generated Go code is not a representation of the exact code that is generated by FIDL. For example, generated structs may have additional fields other than the ones listed in the examples. These should be considered private and ignored in code that uses reflection.
Given the bits definition:
bits FileMode : uint16 { READ = 0b001; WRITE = 0b010; EXECUTE = 0b100; };
FIDL generates a type alias for the underyling type (or uint32
if not specified) and constants for each bits member:
type FileMode uint16 const ( FileModeRead FileMode = 1 FileModeWrite FileMode = 2 FileModeExecute FileMode = 4 )
In addition, it provides the following methods for FileMode
:
func (x FileMode) String() string
: Returns a human readable string of the bits.Given the enum definition:
enum Color { RED = 1; GREEN = 2; BLUE = 3; };
FIDL generates a type alias for the underyling type (or uint32
if not specified) and constants for each enum member:
type Color uint32 const ( ColorRed Color = 1 ColorGreen Color = 2 ColorBlue Color = 3 )
In addition, it provides the following methods for FileMode
:
func (x Color) String() string
: Returns a human readable string of the enum.Given the struct declaration:
struct Person { uint32 id; string name = "john"; };
The FIDL toolchain generates a Person
struct with matching fields:
type Person struct { Id uint32 Name string }
The Go bindings do not currently support default values on struct fields.
Given the union definition:
union JsonValue { 1: reserved; 2: int32 int_value; 3: string string_value; };
FIDL generates an alias and associated constants representing the union tag:
type I_jsonValueTag uint64 const ( JsonValueIntValue = 2 JsonValueStringValue = 3 )
as well as a JsonValue
struct with fields for the tag and each variant of the union:
type JsonValue struct { I_jsonValueTag IntValue int32 StringValue string }
JsonValue
provides the following methods:
func (_m *JsonValue) Which() I_jsonValueTag
: Returns the union tag.func (_m *JsonValue) SetIntValue(intValue int32)
and func (_m *JsonValue) SetStringValue(stringValue string)
: Sets the union to contain a specific variant, updating the tag accordingly.The FIDL toolchain also generates factory functions for constructing instances of JsonValue
:
func JsonValueWithIntValue(intValue int32) JsonValue
func JsonValueWithStringValue(stringValue string) JsonValue
Flexible unions (that is, unions that are prefixed with the flexible
keyword in their FIDL definition) have an extra variant in the generated tag class:
const ( JsonValue_unknownData = 0 // other tags omitted... )
When a FIDL message containing a union with an unknown variant is decoded into JsonValue
, .Which()
will return JsonValue_unknownData
.
Go does not support encoding a flexible union if it has an unknown ordinal. Sending a message containg a union with an unknown variant will cause encoding to fail.
Non-flexible (i.e. strict
) unions fail when decoding a data containing an unknown variant.
Given the following table definition:
table User { 1: reserved; 2: uint8 age; 3: string name; };
The FIDL toolchain generates a User
struct that with presence fields for each non-reserved field:
type User struct { Age uint8 AgePresent bool Name string NamePresent bool }
User
provides the following methods:
func (u *User) HasAge() bool
and func (u *User) HasName() bool
: Checks for the presence of a field.func (u *User) SetAge(age uint8)
and func (u *User) SetName(name string)
: Field setters.func (u *User) GetAge() uint8
and func (u *User) GetName() string
: Field getters.func (u *User) GetAgeWithDefault(_default uint8) uint8
and func (u *User) GetNameWithDefault(_default string) string
: Field getters that return the specified default value if not present.func (u *User) ClearAge()
and func (u *User) ClearName()
: Clears the presence of a field.Given the protocol:
protocol TicTacToe { StartGame(bool start_first); MakeMove(uint8 row, uint8 col) -> (bool success, GameState? new_state); -> OnOpponentMove(GameState new_state); };
Note: The MakeMove
method above returns a bool representing success, and a nullable response value. This is considered un-idiomatic, you should use an error type instead.
FIDL generates a TicTacToeWithCtx
interface which is used by clients when proxying calls to the server, and by the server for implementing the protocol:
type TicTacToeWithCtx interface { StartGame(ctx_ fidl.Context, startFirst bool) error MakeMove(ctx_ fidl.Context, row uint8, col uint8) (bool, *GameState, error) }
Each method will take a Context
as the first argument, followed by the request parameters. Fire and forget methods return error
, and two way methods return the response parameters followed by an error
.
The entry point to interacting with the TicTacToe
protocol is the following function:
func NewTicTacToeWithCtxInterfaceRequest() (TicTacToeWithCtxInterfaceRequest, *TicTacToeWithCtxInterface, error)
This function creates a channel and returns an InterfaceRequest
bound to one end of the channel, representing the server end, and a TicTacToeWithCtxInterface
, bound to the other end, representing the client end.
An example of how to bind the server end to an implementation of the protocol can be found in the Go tutorial. The client end, TicTacToeWithCtxInterface
implements TicTacToeWithCtx
, so clients use those interface methods to make requests. Note that in this implementation, two way method calls are synchronous and block until the response is received.
Implementing a server for this FIDL protocol involves providing a concrete implementation of the TicTacToeWithCtx
interface.
Examples on how to set up and bind a server implementing TicTacToeWithCtx
are covered in the Go tutorial.
TicTacToeWithCtxInterface
provides methods for handling events:
func (p *TicTacToeWithCtxInterface) ExpectOnOpponentMove(ctx_ fidl.Context) (GameState, error)
: Event handler for OnOppponentMove
which takes a Context
and returns the event parameters.Calling any of the event handler methods will read the next buffered event or block until one is received. If the next event matches the method that was called, its parameters are returned. Otherwise, an error is returned. It is up to the client to ensure that the order of received events matches the order of the handled events.
Servers can send events by using the TicTacToeEventProxy
, which provides methods for each event in the protocol:
func (p *TicTacToeEventProxy) OnOpponentMove(newState GameState) error
: Send an OnOpponentMove
event.The Go tutorial contains an example of how to obtain an EventProxy
on the server side.
The Go bindings do not have any special handling for methods with error types.
Given the method with an error type:
protocol TicTacToe { MakeMove(uint8 row, uint8 col) -> (GameState new_state) error MoveError; };
The method signature for MakeMove
on the TicTacToeWithCtx
interface is:
MakeMove(ctx_ fidl.Context, row uint8, col uint8) (TicTacToeMakeMoveResult, error)
TicTacToeMakeMoveResult
is generated as a union with two variants: Err
, which is a MoveError
, and Response
, which is a TicTacToeMakeMoveResponse
.
TicTacToeMakeMoveResponse
is generated as a struct with fields corresponding to a successful response's parameters. In this case it contains a single NewState
field of type GameState
.
FIDL does not have a concept of inheritance, and generates full code as described above for all composed protocols. In other words, the code generated for
protocol A { Foo(); }; protocol B { compose A; Bar(); };
Provides the same API as the code generated for:
protocol A { Foo(); }; protocol B { Foo(); Bar(); };
The generated code is identical except for the method ordinals.
In order to support the [Transitional]
attribute in Go, FIDL generates a TicTacToeWithCtxTransitionalBase
type which provides default implementations for every method marked as [Transitional]
. Server implementations that embed TicTacToeWithCtxTransitionalBase
will continue to build a new transitional method is added.
When marked as [Discoverable]
, the generated InterfaceRequest
type (in this example TicTacToeWithCtxInterfaceRequest
) implements fidl.ServiceRequest
, which allows the server end to be used in service discovery.
In addition, FIDL generates a TicTacToeName
constant that contains the protocol name.