DEV Community

Sergio Méndez
Sergio Méndez

Posted on

Hello world example with gRPC and Go

Hi, readers this time I want to show you how to implement the classic Hello World example with gRPC, but with a small change: instead of sending a Name as a parameter, we are going to modify the protocol buffer definition and the generated code so the client sends a Nickname and the server replies back with it. We are going to use the same style of environment I used in my previous post about Container Runtimes, this time running everything inside a Killercoda Ubuntu playground and a golang container.

This blog post will focus on:

  • Setting up a gRPC + Protoc development environment in Go.
  • Modifying the official grpc-go Hello World example to use a Nickname field.
  • Running the gRPC server and invoking it from a client process.

What you will learn

  • Prepare the environment for gRPC and Protoc
  • Implement a gRPC service
    • Cloning and modifying the grpc-go Hello World example
    • Regenerating protobuf/gRPC Go code
    • Running the gRPC server
  • Invoke a gRPC service from a client

Environment

For this exercise we are going to use the Ubuntu playground on Killercoda, which gives us a disposable Ubuntu machine with Docker already available. As a reference, I'm following the official gRPC Go quickstart guide and adapting it to this custom scenario.

Statement

Implement the gRPC Hello World example so it accepts a Nickname (instead of Name) as a parameter, and invoke it from a client process, similar to the example on the official gRPC site.

Prepare the environment for gRPC and Protoc

1. Inside the Killercoda Ubuntu playground, create a container using the official Go image:

docker run -it golang:1.25-bookworm /bin/bash
Enter fullscreen mode Exit fullscreen mode

2. Prepare the gRPC environment by running the following commands inside the container:

apt-get update;apt-get install unzip;apt-get install nano vim -y
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
apt-get update;apt install protobuf-compiler -y
Enter fullscreen mode Exit fullscreen mode

These commands install:

  • unzip, nano, vim: basic utilities to unpack files and edit code.
  • protoc-gen-go: the Go plugin for the protobuf compiler.
  • protoc-gen-go-grpc: the Go plugin that generates gRPC service code.
  • protobuf-compiler (protoc): the compiler itself, used to generate Go code from .proto files.

Implement a gRPC service

1. Clone the grpc-go repository and remove the pre-generated protobuf files, since we are going to regenerate them after our changes:

git clone -b v1.77.0 --depth 1 https://github.com/grpc/grpc-go
cd grpc-go/examples/helloworld
rm helloworld/helloworld.pb*
Enter fullscreen mode Exit fullscreen mode

2. Modify SayHello so it uses a Nickname parameter instead of Name. We need to touch three files:

  • helloworld/helloworld.proto: change the HelloRequest message to use nickname instead of name.
  • greeter_server/main.go: update the SayHello function to read and log the Nickname field.
  • greeter_client/main.go: update the const and var declarations to use nickname (keep the final GetMessage call as GetMessage, since that is part of the HelloReply message, not the request).

helloworld/helloworld.proto should look like this:

syntax = "proto3";

option go_package = "google.golang.org/grpc/examples/helloworld/helloworld";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the nickname.
message HelloRequest {
  string nickname = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}
Enter fullscreen mode Exit fullscreen mode

In greeter_server/main.go, update the SayHello implementation to read in.GetNickname() and log it:

// server is used to implement helloworld.GreeterServer.
type server struct {
    pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    log.Printf("Nickname Received: %s", in.GetNickname())
    return &pb.HelloReply{Message: "Hello " + in.GetNickname()}, nil
}
Enter fullscreen mode Exit fullscreen mode

In greeter_client/main.go, update the constants and flags to use nickname instead of name:

const (
    address     = "localhost:50051"
    defaultNickname = "Linus"
)

var nickname = flag.String("nickname", defaultNickname, "Nickname to send")
Enter fullscreen mode Exit fullscreen mode

And when calling SayHello, send the Nickname field but keep reading the reply through GetMessage, since the reply message was not modified:

r, err := c.SayHello(ctx, &pb.HelloRequest{Nickname: *nickname})
if err != nil {
    log.Fatalf("could not greet: %v", err)
}
log.Printf("Nickname: %s", r.GetMessage())
Enter fullscreen mode Exit fullscreen mode

3. Recompile the protobuf definition so the Go structs and gRPC stubs match our changes:

protoc --go_out=. --go_opt=paths=source_relative \
    --go-grpc_out=. --go-grpc_opt=paths=source_relative \
    helloworld/helloworld.proto
Enter fullscreen mode Exit fullscreen mode

4. Run the server:

go run greeter_server/main.go
Enter fullscreen mode Exit fullscreen mode

Wait until you see an output similar to this one:

2026/01/21 22:05:25 server listening at [::]:50051
Enter fullscreen mode Exit fullscreen mode

Invoke a gRPC service from a client

5. Open a new terminal and access the same running container using docker exec. Once inside, run the client passing a nickname value:

cd grpc-go/examples/helloworld
go run greeter_client/main.go --nickname=linus2026
Enter fullscreen mode Exit fullscreen mode

Expected results

Expected output on the server side:

Nickname Received: linus2026
Enter fullscreen mode Exit fullscreen mode

Expected output on the client side (or similar):

2026/01/23 22:12:27 Nickname: linus2026
Enter fullscreen mode Exit fullscreen mode

Conclusion about gRPC Hello World

This small exercise shows how easy it is to adapt the official gRPC Hello World example to fit a different use case, just by editing the .proto file, regenerating the stubs with protoc, and updating the server and client logic. Understanding this basic flow (proto definition → code generation → server implementation → client invocation) is the foundation for building more complex gRPC services in Go and other languages.

Thanks for reading! Last to say, see you in my next blog post.

References

Top comments (0)