Example hello-world service uses https://github.com/srlk/go-fx-grpc-starter boilerplate code.


A hello world grpc service is created with hello.proto definition

syntax = "proto3";
option go_package = "github.com/srlk/go-fx-grpc-hello-world/hello";

package hello;

message HelloRequest {
  string from = 1;
  string to = 2;

message HelloResponse {
  string greeting = 1;

service HelloService {
  rpc SayHello(HelloRequest) returns (HelloResponse) {}

HelloService code is generated using protoc tool.

AppService in appservice.go registers and implements HelloService service.

// appservice.go

// Service provider - can receive args to be injected by uber/fx
func NewAppService() fxgrpc.FxGrpcServiceDefinition {
	return AppService{}

// Service object
type AppService struct {

// Register hello service
func (me AppService) RegisterService(grpcServer *grpc.Server) {
	RegisterHelloServiceServer(grpcServer, &me)


// Implement hello service
func (me *AppService) SayHello(ctx context.Context, req *HelloRequest) (*HelloResponse, error) {
	return &HelloResponse{
		Greeting: fmt.Sprintf("Hello %s! I am %s.", req.From, req.To),
	}, nil

Main method of main.go basically teaches uber/fx how to create the service and run it.

// main.go

func main() {
		fx.Provide(NewAppService), // Provide Service

Modifying Service

Service can be which can be modified and recreated by updating hello.proto file.

After modification it’s necessary to re-run protoc to re-generate service code. (or alternatively running genservice.sh)

Calling Service

Example app can be run directly

go run main.go appservice.go

While the server is running, the service can be called using grpcurl tool via command line with below example request. (or alternatively running grpc-cli.sh)

grpcurl \
    -import-path ./hello \
    -proto hello.proto  \
    -plaintext \
    -d '{"from": "Serol", "to": "Erol"}' localhost:9090 hello.HelloService.SayHello


  "greeting": "Hello Serol! I am Erol."


View Github