Communication between JavaScript and Go
GOX allows you to transfer values between JavaScript, Go and HTTP responses without reserializing them manually.
Pages, Actions and WebSocket use this system according to their own communication model:
| Area | JavaScript to Go | Go to the client |
|---|---|---|
| Pages | They do not receive arguments through this system. | They build an HTTP response |
| Actions | They get arguments. | They return a result |
| WebSocket | They receive events and requests | They send out events and responses |
Although the three areas work with similar types, each transport determines how the result is delivered. gox.File returned by a Page is part of the HTTP response; the same type returned by an Action or sent by WebSocket becomes a File JavaScript.
Automatic conversion
GOX uses the types declared in Go to validate and convert the values received.
type Profile struct {
Name string
Age int
}
func GetProfile(name string, age int) gox.Action {
return Profile{Name: name, Age: age}
} const [profile, err] = await Actions.GetProfile("George", 30)
console.log(profile.Name)
console.log(profile.Age) GOX converts the first argument to string, the second int and rebuilds the result as a Object JavaScript.
You do not need to parse JSON, convert numbers manually, or declare an additional schema.
Communication directions
Pages
The Pages respond to HTTP requests. They do not receive arguments sent directly from JavaScript via this system, but they can use different Go types to build the response.
func Download() gox.Page {
file, err := gox.NewFile(gox.FileConfig{
Path: "documents/report.pdf",
})
if err != nil {
return err
}
return file
} A Page can respond with text, HTML, binary data, a stream or a gox.FileThe browser receives the result as an HTTP response.
Headers, cookies and the status code are administered by ctx.Response.
Actions
The Actions receive arguments from JavaScript and return a result:
const [result, err] = await Actions.UpdateProfile({
Name: "George",
Active: true,
}) type Profile struct {
Name string
Active bool
}
func UpdateProfile(profile Profile) gox.Action {
return profile
} The signature determines the amount, order and types expected. GOX validates the arguments before running the function and converts the result to a JavaScript-compatible representation.
WebSocket
WebSocket exchanges one or more values through events and requests:
socket.emit("greeting", "George") socket.On("greeting", func(name string) {
socket.Emit("greeting", "Hola, "+name)
}) The same rules apply to sockets, groups and channels.
Types of values
GOX supports the following categories:
| Category | Examples in JavaScript | Examples in Go |
|---|---|---|
| Basic values | string, boolean, number, bigint | string, bool, int, float, big.Int |
| Structured values | Object, Array | struct, map, slice, array |
| Dates | Date | time.Time |
| Nil values | null | Type that supports nil |
| Binary data | ArrayBuffer, view, Blob | []byte, io.Reader |
| Files | File, File[], FileList | gox.File, []gox.File |
| HTML | HTMLElement, DocumentFragment | Template |
The availability and final representation depend on the area used. See the corresponding reference:
Arguments and signatures
Actions and WebSocket assign the arguments by position.
func Transfer(from string, to string, amount float64) gox.Action {
...
} const [result, err] = await Actions.Transfer("usr_george", "usr_maria", 125.50) The first argument is that from, the second to and the third amount.
GOX checks before running the function or handler:
- The amount of arguments.
- The order of values.
- Compatibility with the declared types.
- The conversion of the elements contained in
struct,map,sliceandarray.
The parameters automatically provided by GOX, such as *gox.Context or the socket that originated a channel event, are not sent from JavaScript.
Representation by transport
The same type may be delivered differently according to the mechanism used.
| Go value | Page | Action | WebSocket |
|---|---|---|---|
| Core value | HTTP response content | JavaScript value | Argument of the event |
struct, map, slice, array | HTTP response content | Object or Array | Object or Array |
Template | HTML response | HTMLElement or DocumentFragment | HTMLElement or DocumentFragment |
[]byte | Binary body | ReadableStream | Uint8Array |
io.Reader | Progressive response | ReadableStream | Not available as stream |
gox.File | File in HTTP response | File | File |
[]gox.File | Not available | File[] | File[] |
This difference allows each area to preserve the natural behavior of its transport.
Conversion errors
If an argument cannot be converted to the expected type, GOX does not run the function or the handler.
func UpdateAge(age int) gox.Action {
...
} const [result, err] = await Actions.UpdateAge("invalid") Actions deliver the problem through their error result. WebSocket communicates it through the event error corresponding. Errors produced when building a Page response are administered as errors of the HTTP request.
Integration with Go
GOX uses the signatures and the usual types of Go as a communication contract. struct describes a known structure, a map represents dynamic keys and a slice allows to receive or return a sequence.
Types like gox.File they keep information that cannot be represented by a basic value. Templates are part of the GOX syntax and allow to return HTML without manually building a type of transport.
It is not necessary to create exclusive models for communication when the application types already correctly describe the information.
Best practices
- It uses specific types in the signatures of Actions and handlers.
- Preference
structwhen the structure of aObjectbe known. - Use
maponly when the keys are dynamic. - It retains the same order between the arguments sent and the declared parameters.
- Use
gox.Filewhen the name and type of the file are relevant. - It uses binary data for content without file identity.
- It uses streams when the content is to be consumed progressively.
- Avoid manually converting values that GOX can transfer directly.
- Handle the errors according to the area used.