Skip to main content

Overview

The Restate Go SDK is open source and can be found on GitHub: (sdk-go repo).

🚀Set up your project in seconds

Have a look at the Go Quickstart!

Add the github.com/restatedev/sdk-go dependency to your project to start developing Restate services.

The Restate SDK lets you implement handlers. Handlers can either be part of a Service, or a Virtual Object. Let's have a look at how to define them.

Services

Services and their handlers are defined as follows:

package main
import (
"context"
"fmt"
"log"
restate "github.com/restatedev/sdk-go"
server "github.com/restatedev/sdk-go/server"
)
type MyService struct{}
func (MyService) MyHandler(ctx restate.Context, greeting string) (string, error) {
return fmt.Sprintf("%s!", greeting), nil
}
func main() {
if err := server.NewRestate().
Bind(restate.Reflect(MyService{})).
Start(context.Background(), "0.0.0.0:9080"); err != nil {
log.Fatal(err)
}
}
  • Define a Service by implementing exported methods on any struct.
  • By default, the service name is the name of the struct, so the service can be called at <RESTATE_INGRESS_URL>/MyService/MyHandler.
  • The service definition contains a list of handlers. Each handler is just function that implements the handler logic. The handler will be named the same way as the method. The function has the Restate Context as its first argument. Within the handler, you use the Context to interact with Restate. The SDK stores the actions you do on the context in the Restate journal to make them durable.
  • The handler input parameters and return type can be of any type, as long as they can be serialized. By default, serialization is done with JSONCodec which uses encoding/json. Input types, output types, and even errors are not mandatory and can be omitted if your handler doesn't need them.
  • Pass the MyService struct to restate.Reflect which uses reflection to turn the methods into handlers. It will skip unexported methods and those that don't have the expected signature - see the package documentation for a list of allowed signatures.
  • Finally, create a server listening on the specified address and bind the service(s) to it.

Virtual Objects

Virtual Objects and their handlers are defined similarly to services, with the following differences:

package main
import (
"context"
"fmt"
"log"
restate "github.com/restatedev/sdk-go"
server "github.com/restatedev/sdk-go/server"
)
type MyVirtualObject struct{}
func (MyVirtualObject) MyHandler(ctx restate.ObjectContext, greeting string) (string, error) {
return fmt.Sprintf("%s %s!", greeting, restate.Key(ctx)), nil
}
func (MyVirtualObject) MyConcurrentHandler(ctx restate.ObjectSharedContext, greeting string) (string, error) {
return fmt.Sprintf("%s %s!", greeting, restate.Key(ctx)), nil
}
func main() {
if err := server.NewRestate().
Bind(restate.Reflect(MyVirtualObject{})).
Start(context.Background(), "0.0.0.0:9080"); err != nil {
log.Fatal(err)
}
}
  • The first argument of each handler must be the ObjectContext parameter. Handlers with the ObjectContext parameter can write to the K/V state store. Only one handler can be active at a time, to ensure consistency.
  • If you want to have a handler that executes concurrently to the others and doesn't have write access to the K/V state, instead use the ObjectSharedContext. For example, you can use these handlers to read K/V state, or interact with the blocking handler.
Prefer to start with a service definition?

The Go SDK also supports defining handlers and input/output types using code generation from Protocol Buffers. See Code Generation for more details.

Now that you have a high-level idea of what a Restate service might look like, let's have a look at what the Restate Context allows you to do.