Parameters

The Actions receive data using function parameters.

GOX automatically converts the values sent from JavaScript to the corresponding Go type before invoking the Action.

The function receives directly the values declared in its signature, without the need to read the body of an request, parse JSON or manually access HTTP parameters.


Basic parameters

The parameters of an Action are declared using the same syntax as any Go function.

gox
func Greeting(name string) gox.Action {
    return "Hello, " + name
}

The Action is invoked from JavaScript by passing the arguments in the same order in which they were declared.

javascript
const [message, err] = await Actions.Greeting("George")

An Action can declare several parameters.

gox
func Sum(a int, b int) gox.Action {
    return a + b
}
javascript
const [result, err] = await Actions.Sum(10, 20)

The arguments are assigned by position. The first value sent corresponds to the first parameter, the second value to the second parameter and so on.


Data types

The parameters can use basic types of Go.

gox
func UpdateProfile(name string, age int, active bool) gox.Action {
    ...
}
javascript
const [result, err] = await Actions.UpdateProfile("George", 30, true)

GOX converts each argument to the type declared in the signature before running the Action.

Slices, maps, structures and other composite types can also be used when the value sent from JavaScript can be represented by this type.


Structs

JavaScript objects can be received directly as Go structures.

gox
type User struct {
    Name   string
    Age    int
    Active bool
}

func SaveUser(user User) gox.Action {
    ...
}
javascript
const [result, err] = await Actions.SaveUser({
    Name: "George",
    Age: 30,
    Active: true
 })

GOX uses the structure definition to rebuild the value before invoking the Action.

This allows you to work directly with Go types and avoids declaring a separate parameter for each property.


Slices

JavaScript arrays can be received as Go slices.

gox
func DeleteUsers(ids []int) gox.Action {
    ...
}
javascript
const [result, err] = await Actions.DeleteUsers([12, 18, 24])

Each element of the array is converted to the type defined by the slice.


Maps

JavaScript objects can also be received as maps when their properties represent a dynamic collection of values.

gox
func SaveSettings(settings map[string]string) gox.Action {
    ...
}
javascript
const [result, err] = await Actions.SaveSettings({
        language: "es",
        theme: "dark"
    })

Maps are useful when the keys are not part of a fixed structure known during the compilation.

When the data structure is stable, it is generally preferable to use a structure.


Custom types

Actions can receive custom types defined from other types of Go.

gox
type UserID int
type Email string

func InviteUser(id UserID, email Email) gox.Action {
    ...
}
javascript
const [result, err] = await Actions.InviteUser(42, "[email protected]")

GOX retains the type declared in the signature, allowing the Action to work with the same types used by the rest of the application.


Execution context

An Action can receive the execution context using a parameter *gox.Context.

gox
func SaveUser(user User, ctx *gox.Context) gox.Action {
    ...
}

The context should always be declared as the last parameter of the function.

gox
func SaveUser(user User, ctx *gox.Context) gox.Action

The following signature is not valid:

gox
func SaveUser(ctx *gox.Context, user User) gox.Action

The context is not sent from JavaScript. GOX provides it automatically when running the Action.

For this reason, invocation only includes the parameters prior to the context.

javascript
const [result, err] = await Actions.SaveUser({
        Name: "George",
        Age: 30,
        Active: true
    })

Since JavaScript, context presence does not change the public signature of the Action.

The context allows access to the current request, session, response and other resources associated with the execution of the page.


Number of arguments

The Actions use the normal rules of the Go functions.

All declared parameters should be given value and sent in the correct order.

gox
func Transfer(from UserID, to UserID, amount float64) gox.Action {
    ...
}
javascript
const [result, err] = await Actions.Transfer(10, 25, 150.50)

GO does not support optional parameters and the Actions maintain this same behavior.

Variative functions cannot be used as Actions either.

gox
func Invalid(values ...string) gox.Action

When an operation needs to receive a variable amount of values, a slice should be used.

gox
func SaveValues(values []string) gox.Action {
    ...
}
javascript
const [result, err] = await Actions.SaveValues(["first", "second", "third"])

Conversion of values

Before running an Action, GOX converts every JavaScript argument to the type declared in the signature.

gox
func UpdateScore(score int) gox.Action {
    ...
}
javascript
const [result, err] = await Actions.UpdateScore(100)

If the values sent cannot be converted to the expected types, the Action does not run.

gox
func UpdateScore(score int) gox.Action {
    ...
}
javascript
const [result, err] = await Actions.UpdateScore("invalid")

Errors related to invalid arguments are returned by the same error mechanism used by the Actions.


Integration with Go

The parameters of an Action directly use the Go type system.

No annotations, decorators or additional syntax are required to describe the data received. The function signature contains all the information necessary to validate and convert the arguments.

The usual rules of Go are also maintained: the parameters are positional, cannot be optional and the varying functions are not part of the Action model.

The only special parameter is *gox.Context, which can be declared at the end of the signature and is automatically provided by GOX.


Best practices

  • It uses individual parameters when an Action receives few simple values.
  • When several values represent the same entity or operation, add them to a structure.
  • It prefers structures for known structures and maps for collections whose keys are really dynamic.
  • Keep *gox.Context as the last parameter and declare only when the Action needs access to the execution environment.
  • To receive a variable amount of values, use a slice instead of a variable function.

To learn more about ActionsSee your documentation. To learn more about FormsSee your documentation. To learn more about Return valuesSee your documentation. To learn more about Errors, check your documentation.


See also

Next step

It continues with documentation of the forms, where you will learn how to send HTML controls and forms directly to an Action.

Forms