| # 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 |