gRPC-Go: HTTP/2 RPC Framework
Use gRPC-Go to build high-performance RPC services with HTTP/2, code generation, and streaming support.
- Step 1
Check Go version
gRPC-Go requires one of the two latest major Go releases (Go 1.20 or higher). Check your Go version:
go version - Step 2
Create a new Go module
Initialize a new Go module for your gRPC project:
mkdir grpc-example cd grpc-example go mod init grpc-example - Step 3
Install gRPC-Go dependency
Add the gRPC-Go library to your project. Go modules will automatically fetch dependencies when you build or run your code:
import "google.golang.org/grpc" - Step 4
Install Protocol Buffers compiler
gRPC uses Protocol Buffers (protobuf) for defining service interfaces. Install the protobuf compiler (protoc):
# On macOS: brew install protobuf # On Ubuntu/Debian: sudo apt-get install protobuf-compiler # On Arch Linux: sudo pacman -S protobuf # Verify installation: protoc --version - Step 5
Install Go Protocol Buffers plugins
Install necessary tools to generate Go code from protobuf definitions:
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest - Step 6
Define your service in protobuf
Create a .proto file that defines your service interface and message types. This is the contract between client and server:
syntax = "proto3"; package example; option go_package = "grpc-example/pb"; service Greeter { rpc SayHello (HelloRequest) returns (HelloResponse); rpc SayHelloServerStream (HelloRequest) returns (stream HelloResponse); rpc SayHelloClientStream (stream HelloRequest) returns (HelloResponse); rpc SayHelloBidirectionalStream (stream HelloRequest) returns (stream HelloResponse); } message HelloRequest { string name = 1; } message HelloResponse { string greeting = 1; } - Step 7
Generate Go code from protobuf
Use protoc to generate Go files from your .proto definition:
mkdir -p pb protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ pb/hello.proto - Step 8
Implement the gRPC server
Create a server that implements the service defined in your .proto file. The generated Go code provides interfaces you need to implement:
package main import ( "context" "fmt" "io" "log" "net" pb "grpc-example/pb" "google.golang.org/grpc" ) type server struct { pb.UnimplementedGreeterServer } func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) { return &pb.HelloResponse{ Greeting: fmt.Sprintf("Hello, %s!", req.Name), }, nil } func (s *server) SayHelloServerStream(req *pb.HelloRequest, stream pb.Greeter_SayHelloServerStreamServer) error { for i := 0; i < 5; i++ { err := stream.Send(&pb.HelloResponse{ Greeting: fmt.Sprintf("Hello, %s! Message %d", req.Name, i+1), }) if err != nil { return err } } return nil } func (s *server) SayHelloBidirectionalStream(stream pb.Greeter_SayHelloBidirectionalStreamServer) error { for { in, err := stream.Recv() if err == io.EOF { return nil } if err != nil { return err } if err := stream.Send(&pb.HelloResponse{ Greeting: fmt.Sprintf("Echo: Hello, %s!", in.Name), }); err != nil { return err } } } func main() { lis, err := net.Listen("tcp", ":50051") if err != nil { log.Fatalf("failed to listen: %v", err) } grpcServer := grpc.NewServer() pb.RegisterGreeterServer(grpcServer, &server{}) log.Printf("Server starting on port 50051") if err := grpcServer.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } } - Step 9
Create a gRPC client
Implement a client that connects to your gRPC server and makes RPC calls:
package main import ( "context" "fmt" "log" "time" pb "grpc-example/pb" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) func main() { conn, err := grpc.NewClient( "localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()), ) if err != nil { log.Fatalf("failed to connect: %v", err) } defer conn.Close() client := pb.NewGreeterClient(conn) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) resp, err := client.SayHello(ctx, &pb.HelloRequest{Name: "World"}) cancel() if err != nil { log.Fatalf("error when calling SayHello: %v", err) } fmt.Println(resp.Greeting) } - Step 10
Use server streaming
Server streaming allows the server to send multiple responses to a single client request:
import "io" ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) stream, err := client.SayHelloServerStream(ctx, &pb.HelloRequest{Name: "World"}) cancel() if err != nil { log.Fatalf("error when calling SayHelloServerStream: %v", err) } for { resp, err := stream.Recv() if err == io.EOF { break } if err != nil { log.Fatalf("error while receiving: %v", err) } fmt.Println(resp.Greeting) } - Step 11
Configure TLS encryption
gRPC uses TLS for secure communication in production. Generate self-signed certificates for development:
# Generate root CA private key openssl genrsa -out ca.key 4096 # Generate root CA certificate openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt -subj "/CN=MyCA" # Generate server private key and certificate openssl genrsa -out server.key 4096 openssl req -new -key server.key -out server.csr -subj "/CN=localhost" openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -sha256 # Generate client certificate openssl genrsa -out client.key 4096 openssl req -new -key client.key -out client.csr -subj "/CN=client" openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365 -sha256⚠ Heads up: Store your private keys securely. Never commit them to version control. For production, use certificates from trusted CAs. - Step 12
Use TLS in server and client
Configure both server and client to use TLS certificates for secure communication:
import ( "crypto/tls" "crypto/x509" "io/ioutil" "google.golang.org/grpc/credentials" ) // Server-side TLS func createServerTLS() credentials.TransportCredentials { cert, err := tls.LoadX509KeyPair("server.crt", "server.key") if err != nil { log.Fatalf("%v", err) } caCert, err := ioutil.ReadFile("ca.crt") if err != nil { log.Fatalf("%v", err) } caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) return credentials.NewTLS(&tls.Config{ Certificates: []tls.Certificate{cert}, ClientAuth: tls.RequireAndVerifyClientCert, ClientCAs: caCertPool, }) } grpcServer := grpc.NewServer(grpc.Creds(createServerTLS())) // Client-side TLS func createClientTLS() credentials.TransportCredentials { cert, err := tls.LoadX509KeyPair("client.crt", "client.key") if err != nil { log.Fatalf("%v", err) } caCert, err := ioutil.ReadFile("ca.crt") if err != nil { log.Fatalf("%v", err) } caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) return credentials.NewTLS(&tls.Config{ Certificates: []tls.Certificate{cert}, RootCAs: caCertPool, ServerName: "localhost", }) } conn, err := grpc.NewClient("localhost:50051", grpc.WithTransportCredentials(createClientTLS())) - Step 13
Add metadata interceptors
Use interceptors to add metadata (headers) to requests and responses for authentication, logging, and other cross-cutting concerns:
import ( "context" "google.golang.org/grpc/metadata" ) // Server-side unary interceptor to log metadata func unaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { md, ok := metadata.FromIncomingContext(ctx) if ok { authToken := md.Get("authorization") log.Printf("Auth token received: %v", authToken) } return handler(ctx, req) } grpcServer := grpc.NewServer(grpc.UnaryInterceptor(unaryServerInterceptor)) // Client request with metadata ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs("authorization", "Bearer token123")) resp, err := client.SayHello(ctx, &pb.HelloRequest{Name: "World"}) - Step 14
Implement health checking
gRPC provides built-in health checking service for monitoring and load balancing:
import ( "google.golang.org/grpc/health" "google.golang.org/grpc/health/grpc_health_v1" ) func main() { lis, err := net.Listen("tcp", ":50051") if err != nil { log.Fatalf("failed to listen: %v", err) } grpcServer := grpc.NewServer() pb.RegisterGreeterServer(grpcServer, &server{}) // Register health server healthServer := health.NewServer() healthServer.SetServingStatus("", grpc_health_v1.HealthCheckResponse_SERVING) healthServer.SetServingStatus("Greeter", grpc_health_v1.HealthCheckResponse_SERVING) grpc_health_v1.RegisterHealthServer(grpcServer, healthServer) if err := grpcServer.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } } // Health check client healthClient := grpc_health_v1.NewHealthClient(conn) resp, err := healthClient.Check(ctx, &grpc_health_v1.HealthCheckRequest{Service: "Greeter"}) fmt.Printf("Health status: %v\n", resp.Status) - Step 15
Configure keepalive
Keepalive settings help maintain connections and detect dead peers in long-running services:
import ( "time" "google.golang.org/grpc/keepalive" ) // Server keepalive configuration grpcServer := grpc.NewServer( grpc.KeepaliveParams(keepalive.ServerParameters{ Time: 10 * time.Second, Timeout: 3 * time.Second, PermitWithoutStream: true, }), ) // Client keepalive configuration conn, err := grpc.NewClient("localhost:50051", grpc.WithKeepaliveParams(keepalive.ClientParameters{ Time: 10 * time.Second, Timeout: 3 * time.Second, PermitWithoutStream: true, }), ) - Step 16
Deploy with Docker
Containerize your gRPC service for easy deployment and scaling:
FROM golang:1.21-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -o server ./server.go FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=builder /app/server . COPY --from=builder /app/server.crt /app/server.key /app/ca.crt . EXPOSE 50051 CMD ["./server"] - Step 17
Enable gRPC logging
Enable verbose logging for debugging gRPC internals:
# Enable gRPC logging export GRPC_GO_LOG_VERBOSITY_LEVEL=99 export GRPC_GO_LOG_SEVERITY_LEVEL=info # Run your server and see detailed logs # Logs include connection details, stream state, and error traces - Step 18
Explore gRPC-Go examples
The gRPC-Go repository contains many examples demonstrating additional features like OAuth2 authentication, name resolution, and more at the examples/ directory:
# Clone the gRPC-Go repository to explore examples git clone https://github.com/grpc/grpc-go cd grpc-go/examples # Available examples: # - features/authentication - OAuth2 authentication # - features/name_resolving - DNS service discovery # - features/cancellation - Request cancellation # - features/compression - Message compression # - features/deadline - Request deadlines # - features/error_details - Detailed error handling
Feature requests
Sign in to suggest features or vote on existing ones.
No feature requests yet.
Discussion
Sign in to join the discussion.
No comments yet.