blob: 9e9974780da39d845502051b0804ea5d32649a7f [file] [log] [blame] [view]
# Go bindings
## Libraries {#libraries}
Given the `library` declaration:
library fuchsia.examples;
Bindings code is generated into a `examples` Go package, which is obtained by
taking the last component of the FIDL library name.
The package can be imported using the path:
import "fidl/fuchsia/examples"
## Constants {#constants}
[Constants][lang-constants] are generated as a `const` block. For example, the
following constants:
{%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="consts" %}
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](#builtins).
## Fields {#fields}
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.
### Built-in types {#builtins}
The FIDL types are converted to Go types based on the following table.
|FIDL Type|Go Type|
|--- |--- |
|`request<P>`|The generated server end type `PInterfaceRequest`, see [Protocols](#protocols)|
|`P`|The generated client end type `PInterface`, see [Protocols](#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|
### User defined types {#user-defined-types}
In Go, a user defined type (bits, enum, constant, struct, union, or table) is
referred to using the generated type (see [Type Definitions](#type-definitions)).
The nullable version of a user defined type `T` is referred to using a pointer
to the generated type: `*T`.
## Type definitions {#type-definitions}
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
include non-exported fields that cannot be inspected with reflection.
### Bits {#bits}
Given the [bits][lang-bits] definition:
{%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="consts" %}
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
Example usage:
{%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/go/fidl_packages/fidl_test.go" region_tag="bits" %}
### Enums {#enums}
Given the [enum][lang-enums] definition:
{%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="enums" %}
FIDL generates a type alias for the underyling type (or `uint32` if not
specified) and constants for each enum member:
type LocationType uint32
const (
LocationTypeMuseum LocationType = 1
LocationTypeAirport LocationType = 2
LocationTypeRestaurant LocationType = 3
In addition, it provides the following methods for `LocationType`:
* `func (x LocationType) String() string`: Returns a human readable string of the enum.
Example usage:
{%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/go/fidl_packages/fidl_test.go" region_tag="enums" %}
### Structs {#structs}
Given the [struct][lang-structs] declaration:
{%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="structs" %}
The FIDL toolchain generates a `Color` struct with matching fields:
type Color struct {
Id uint32
Name string
The Go bindings do not currently support default values on struct fields.
Example usage:
{%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/go/fidl_packages/fidl_test.go" region_tag="structs" %}
### Unions {#unions}
Given the union definition:
{%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="unions" %}
FIDL generates an alias and associated constants representing the
[union tag][union-lexicon]:
type I_jsonValueTag uint64
const (
JsonValueIntValue = 2
JsonValueStringValue = 3
as well as a `JsonValue` struct with fields for the tag and each
[variant][union-lexicon] of the union:
type JsonValue struct {
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`
Example usage:
{%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/go/fidl_packages/fidl_test.go" region_tag="unions" %}
#### Flexible unions and unknown variants
[Flexible unions][lang-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.
### Tables {#tables}
Given the following [table][lang-tables] definition:
{%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="tables" %}
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
* `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.
Example usage:
{%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/go/fidl_packages/fidl_test.go" region_tag="tables" %}
## Protocols {#protocols}
Given the [protocol][lang-protocols]:
{%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="protocols" %}
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](#protocols-results)
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)
<!-- TODO: link to API docs -->
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
func NewTicTacToeWithCtxInterfaceRequest() (TicTacToeWithCtxInterfaceRequest, *TicTacToeWithCtxInterface, error)
This function creates a channel and returns a `TicTacToeWithCtxInterfaceRequest`
bound to one end of the channel, representing the server end, and a
`TicTacToeWithCtxInterface`, bound to the other end, representing the client
end. These are explained in the [client](#client) and [server](#server)
### Client {#client}
The client end of a channel used to communicate over the `TicTacToe` protocol
is the `TicTacToeWithCtxInterface`. It implements the `TicTacToeWithCtx`
interface described in [Protocols](#protocols) as well as methods for handling
[events](#events). Note that in this implementation, two way method calls are
synchronous and block until the response is received.
An example of a Go FIDL client can be found in [//examples/fidl/go/client][example-client].
### Server {#server}
Implementing a server for this FIDL protocol involves providing a concrete
implementation of the `TicTacToeWithCtx` interface.
The bindings generate a `TicTacToeWithCtxInterfaceRequest` type, used to
represent the server end of the channel communicating over the `TicTacToe`
protocol. It provides the following methods:
* `func (c EchoWithCtxInterfaceRequest) ToChannel() zx.Channel`: Convert the
interface request back to an untyped channel.
An example of a Go FIDL server can be found in [//examples/fidl/go/server][example-server].
### Events {#events}
#### Client
`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 - the caller is expected to drain the event buffer
promptly to avoid unbounded buffering in the FIDL bindings. 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.
#### Server
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.
Creating a `TicTacToeEventProxy` requires access to a channel to the client.
The [Go server example][example-server] shows how to obtain an
`EventProxy` on the server side.
### Results {#protocols-results}
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](#protocols) is:
MakeMove(ctx_ fidl.Context, row uint8, col uint8) (TicTacToeMakeMoveResult, error)
`TicTacToeMakeMoveResult` is generated as a [union](#unions) with two variants:
`Err`, which is a `MoveError`, and `Response`, which is a
`TicTacToeMakeMoveResponse` is generated as a [struct](#structs) with fields
corresponding to a successful response's parameters. In this case it contains a
single `NewState` field of type `GameState`.
### Protocol composition {#protocol-composition}
FIDL does not have a concept of inheritance, and generates full code as
described above for all [composed protocols][lang-protocol-composition]. In
other words, the code generated for
protocol A {
protocol B {
compose A;
Provides the same API as the code generated for:
protocol A {
protocol B {
The generated code is identical except for the method ordinals.
### Protocol and method attributes {#protocol-and-method-attributes}
#### Transitional {#transitional}
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.
#### Discoverable
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.
<!-- xrefs -->
[example-client]: /examples/fidl/go/client
[example-server]: /examples/fidl/go/server
[lang-constants]: /docs/reference/fidl/language/
[lang-bits]: /docs/reference/fidl/language/
[lang-enums]: /docs/reference/fidl/language/
[lang-structs]: /docs/reference/fidl/language/
[lang-tables]: /docs/reference/fidl/language/
[lang-unions]: /docs/reference/fidl/language/
[lang-protocols]: /docs/reference/fidl/language/
[lang-protocol-composition]: /docs/reference/fidl/language/
[union-lexicon]: /docs/reference/fidl/language/