Golang grpc: how to determine when the server has started listening?


So I have the following:

type Node struct {
    Table map[string]string
    address string

func (n *Node) Start() {
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)

    s := grpc.NewServer()
    thing.RegisterGreeterServer(s, n)
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)

In my main function I’ll spin up mulitple nodes like so:

func main() {
    n :=Node{Table: map[string]string{}}
    go n.Start()
    conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())


The problem is, because I’m spinning up the node concurrently, there’s a chance the dial up connection might not work because the node might not have been setup yet.

Ideally, I’d like a done channel that tells me when the grpc server has actually started listening. How do I accomplish this?

This is essntially the same problem as How to add hook on golang grpc server start? which doesn’t have an answer


s.Serve(listener) blocks, so you can’t achieve your purpose by having a done chan, instead you have to implement the healthcheck and readiness for your service, and check those before performing any request by the client.
The server should implement the following proto:

syntax = "proto3";

package grpc.health.v1;

message HealthCheckRequest {
  string service = 1;

message HealthCheckResponse {
  enum ServingStatus {
    UNKNOWN = 0;
    SERVING = 1;
    NOT_SERVING = 2;
    SERVICE_UNKNOWN = 3;  // Used only by the Watch method.
  ServingStatus status = 1;

service Health {
  rpc Check(HealthCheckRequest) returns (HealthCheckResponse);

  rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);

For example, the envoy proxy grpc_health_check works with the above proto.

Read GRPC Health Checking Protocol for more information.

Answered By – meshkati

Answer Checked By – David Marino (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.