package main import ( "context" "log" "net" "net/http" "sync" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" helloworldpb "go-grpc-gateway-template/proto/helloworld" ) type server struct { helloworldpb.UnimplementedGreeterServer } func (s *server) SayHello(ctx context.Context, req *helloworldpb.HelloRequest) (*helloworldpb.HelloReply, error) { return &helloworldpb.HelloReply{ Message: "Hello " + req.GetName(), }, nil } func main() { // Create a listener on TCP port lis, err := net.Listen("tcp", ":8080") if err != nil { log.Fatalln("Failed to listen:", err) } // Create a gRPC server object s := grpc.NewServer() // Attach the Greeter service to the server helloworldpb.RegisterGreeterServer(s, &server{}) var wg sync.WaitGroup wg.Add(2) // Serve gRPC server log.Println("Serving gRPC on 0.0.0.0:8080") go func() { defer wg.Done() if err := s.Serve(lis); err != nil { log.Fatalln("Failed to serve:", err) } }() // Create a client connection to the gRPC server we just started // This is where the gRPC-Gateway proxies the requests conn, err := grpc.DialContext( context.Background(), "0.0.0.0:8080", grpc.WithBlock(), grpc.WithTransportCredentials(insecure.NewCredentials()), ) if err != nil { log.Fatalln("Failed to dial server:", err) } gwmux := runtime.NewServeMux() // Register Greeter err = helloworldpb.RegisterGreeterHandler(context.Background(), gwmux, conn) if err != nil { log.Fatalln("Failed to register gateway:", err) } gwServer := &http.Server{ Addr: ":8090", Handler: gwmux, } log.Println("Serving gRPC-Gateway on http://0.0.0.0:8090") go func() { defer wg.Done() if err := gwServer.ListenAndServe(); err != nil { log.Fatalln("Failed to serve gRPC-Gateway:", err) } }() wg.Wait() }