listener, err := net.Listen("tcp", ":50051")
- Basic version
- With server option(s)
opts := []grpc.ServerOption{
opt1, opt2, opt3
}
s := grpc.NewServer(opts...)
- Unary interceptor
grpc.UnaryInterceptor(unaryInterceptorFunc)
- Stream interceptor
grpc.StreamInterceptor(streamInterceptorFunc)
- Register single service
type abcServer struct {}
pb.RegisterAbcServer(s, &abcServer{}) // Abc is the service name
- Register multiple services
type abcServer struct {}
type xyzServer struct {}
abc_pb.RegisterAbcServer(s, &abcServer{}) // Abc is the service name
xyz_pb.RegisterXyzServer(s, &xyzServer{}) // Xyz is the service name
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
type abcServer struct {}
func (s *abcServer) RemoteFunc1(ctx context.Context, input *InputType) (*OutputType, error) {}
func (s *abcServer) RemoteFunc2(ctx context.Context, input *InputType) (*OutputType, error) {}
func (s *abcServer) RemoteFunc3(ctx context.Context, input *InputType) (*OutputType, error) {}
- Process unary input
type abcServer struct {}
func (s *abcServer) RemoteFunc(ctx context.Context, input *InputType) (*OutputType, error) {
// Use input directly.
}
- Process stream intput
type abcServer struct {}
func (s *abcServer) RemoteFunc(stream pb.Abc_RemoteFuncServer) error {
for {
input, err := stream.Recv()
if err == io.EOF {
return stream.SendAndClose(output) // At the end of input stream, return the output.
}
if err != nil {
return err
}
// Process single input.
}
}
- Process metadata
- In unary input function
func (s *abcServer) RemoteFunc(ctx context.Context, input *InputType) (*OutputType, error) {
md, ok := metadata.FromIncomingContext(ctx)
}
- In stream input function
func (s *abcServer) RemoteFunc(stream pb.Abc_RemoteFuncServer) error {
md, ok := metadata.FromIncomingContext(stream.Context())
}
- Return unary output
func (s *abcServer) RemoteFunc(ctx context.Context, input *InputType) (*OutputType, error) {
return &output, status.New(codes.OK, "").Err()
}
- Return stream output
func (s *abcServer) RemoteFunc(input *InputType, stream pb.Abc_RemoteFuncServer) error {
for _ , output := range output {
err := stream.Send(&output)
}
return nil
}
- Return metadata
- In unary input function
func (s *abcServer) RemoteFunc(ctx context.Context, input *InputType) (*OutputType, error) {
header := metadata.Pairs("header-key", "val")
grpc.SendHeader(ctx, header)
trailer := metadata.Pairs("trailer-key", "val")
grpc.SetTrailer(ctx, trailer)
}
- In stream input function
func (s *abcServer) RemoteFunc(stream pb.Abc_RemoteFuncServer) error {
header := metadata.Pairs("header-key", "val")
stream.SendHeader(header)
trailer := metadata.Pairs("trailer-key", "val")
stream.SetTrailer(trailer)
}
- Return error
- Only error status
errorStatus := status.New(codes.ErrorCodeOption, "The error description.") // ErrorCodeOption needs to be replaced by real option.
return errorStatus.Err()
- error status with details
import epb "google.golang.org/genproto/googleapis/rpc/errdetails"
errorStatus := status.New(codes.ErrorCodeOption, "The error description.") // ErrorCodeOption needs to be replaced by real option.
ds, err := errorStatus.WithDetails(
&epb.DetailOption1{}, // DetailOption1 needs to be replaced by real option.
&epb.DetailOption2{}, // DetailOption2 needs to be replaced by real option.
&epb.DetailOption3{} // DetailOption3 needs to be replaced by real option.
)
return ds.Err()