blob: 53668b7c35cd8c3fe789e601b1679dbf8cd3b8b3 [file] [log] [blame] [view]
# Go bindings
## Libraries {#libraries}
Given the `library` declaration:
```fidl
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:
```golang
import "fidl/fuchsia/examples"
```
## Constants {#constants}
[Constants][lang-constants] are generated as a `const` block. For example, the
following constants:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="consts" %}
```
Are generated as:
```golang
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|
|--- |--- |
|`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`|The generated server end type `PInterfaceRequest`, see [Protocols](#protocols)|
|`client_end:P`|The generated client end type `PInterface`, see [Protocols](#protocols)|
|`zx.Handle:S`,`zx.Handle:<S, optional>`|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|
|`zx.Handle`,`zx.Handle:optional`|`zx.Handle`|
### 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:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="consts" %}
```
FIDL generates a type alias for the underlying type (or `uint32` if not
specified) and constants for each bits member:
```golang
type FileMode uint16
const (
FileModeRead FileMode = 1
FileModeWrite FileMode = 2
FileModeExecute FileMode = 4
FileMode_Mask FileMode = 7
)
```
The `FileMode_Mask` value is a bitmask that contains every bits member defined
in the FIDL schema.
In addition, it provides the following methods for `FileMode`:
* `func (x FileMode) String() string`: Returns a human readable string of the
bits.
* `func (x FileMode) GetUnknownBits() uint64`: Returns a value that contains only
the unknown members from this bits value, as a `uint64`. Always returns 0 for
[strict][lang-flexible] bits.
* `func (x FileMode) HasUnknownBits() bool`: Returns whether this value contains
any unknown bits. Always returns `false` for [strict][lang-flexible] bits.
* `func (x FileMode) InvertBits() FileMode`: Inverts all known bits. All
unknown bits are set to false.
* `func (x FileMode) ClearBits(mask FileMode) FileMode`: Modifies the bitfield
such that all bits set in the mask are unset.
* `func (x FileMode) HasBits(mask FileMode) bool`: Validates that all flipped
bits in the mask are set.
Example usage:
```go
{% 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:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="enums" %}
```
FIDL generates a type alias for the underlying type (or `uint32` if not
specified) and constants for each enum member:
```golang
type LocationType uint32
const (
LocationTypeMuseum LocationType = 1
LocationTypeAirport LocationType = 2
LocationTypeRestaurant LocationType = 3
)
```
If `LocationType` is [flexible][lang-flexible], it will have an unknown
placeholder member as well:
```golang
LocationType_Unknown LocationType = 0x7fffffff
```
If the enum has a member tagged with the [`[Unknown]`][unknown-attr] attribute,
the generated unknown variable will have the same value as the tagged unknown
member.
`LocationType` provides the following methods:
* `func (x LocationType) IsUnknown() bool`: Returns whether this enum value is
unknown. Always returns `false` for [strict][lang-flexible] enums.
* `func (x LocationType) String() string`: Returns a human readable string of
the enum.
Example usage:
```go
{% 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:
```fidl
{% 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:
```golang
type Color struct {
Id uint32
Name string
}
```
The Go bindings do not currently support default values on struct fields.
Example usage:
```go
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/go/fidl_packages/fidl_test.go" region_tag="structs" %}
```
### Unions {#unions}
Given the union definition:
```fidl
{% 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]:
```golang
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:
```golang
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.
If `JsonValue` is [flexible][lang-flexible], it will have the following
additional methods:
* `func (_m *JsonValue) GetUnknownData() fidl.UnknownData`: Returns the raw
bytes and handles of the unknown data. The slice of handles is returned in
[traversal order][traversal], and is guaranteed to be empty if the union is
a [resource][lang-resource] type.
The FIDL toolchain also generates factory functions for constructing instances
of `JsonValue`:
* `func JsonValueWithIntValue(intValue int32) JsonValue`
* `func JsonValueWithStringValue(stringValue string) JsonValue`
Example usage:
```go
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/go/fidl_packages/fidl_test.go" region_tag="unions" %}
```
#### Flexible unions and unknown variants
[Flexible][lang-flexible] unions have an extra variant in the generated tag
class:
```golang
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`.
Encoding a union with an unknown variant writes the unknown data and the
original ordinal back onto the wire.
[Strict][lang-flexible] unions fail when decoding an unknown variant.
[Flexible][lang-flexible] unions that are [value][lang-resource] types fail when
decoding an unknown variant with handles.
### Tables {#tables}
Given the following [table][lang-tables] definition:
```fidl
{% 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
field:
```golang
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.
* `func (u *User) HasUnknownData() bool`: Checks for the presence of any unknown
fields.
* `func (u *User) GetUnknownData() map[uint64]fidl.UnknownData`: Returns a map
from ordinal to bytes and handles for any unknown fields. The list of handles
is returned in [traversal order][traversal], and is guaranteed to be empty if
the table is a [value][lang-resource] type.
Example usage:
```go
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/go/fidl_packages/fidl_test.go" region_tag="tables" %}
```
### Inline layouts
The generated Go code uses the [the name reserved by `fidlc`][anon-names] for
inline layouts.
## Protocols {#protocols}
Given the [protocol][lang-protocols]:
```fidl
{% 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)
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:
```golang
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
function:
```golang
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)
sections.
### 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:
```fidl
protocol TicTacToe {
MakeMove(struct {
row uint8;
col uint8;
}) -> (struct {
new_state GameState;
}) error MoveError;
};
```
The method signature for `MakeMove` on the [`TicTacToeWithCtx`
interface](#protocols) is:
```golang
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`.
`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
```fidl
protocol A {
Foo();
};
protocol B {
compose A;
Bar();
};
```
Provides the same API as the code generated for:
```fidl
protocol A {
Foo();
};
protocol B {
Foo();
Bar();
};
```
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 -->
[anon-names]: /docs/reference/fidl/language/language.md#inline-layouts
[example-client]: /examples/fidl/go/client
[example-server]: /examples/fidl/go/server
[lang-constants]: /docs/reference/fidl/language/language.md#constants
[lang-bits]: /docs/reference/fidl/language/language.md#bits
[lang-enums]: /docs/reference/fidl/language/language.md#enums
[lang-flexible]: /docs/reference/fidl/language/language.md#strict-vs-flexible
[lang-structs]: /docs/reference/fidl/language/language.md#structs
[lang-tables]: /docs/reference/fidl/language/language.md#tables
[lang-protocols]: /docs/reference/fidl/language/language.md#protocols
[lang-resource]: /docs/reference/fidl/language/language.md#value-vs-resource
[lang-protocol-composition]: /docs/reference/fidl/language/language.md#protocol-composition
[union-lexicon]: /docs/reference/fidl/language/lexicon.md#union-terms
[traversal]: /docs/reference/fidl/language/wire-format/README.md#traversal-order
[unknown-attr]: /docs/reference/fidl/language/attributes.md#unknown