grpc

package module
v1.3.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 24, 2025 License: MIT Imports: 16 Imported by: 0

README

English  |  中文

goner/grpc Component Usage Guide

This document explains how to use the goner/grpc component, covering both the traditional approach and the Gone V2 Provider mechanism.

Getting Started

First, create a grpc directory and initialize a golang mod in it:

mkdir grpc
cd grpc
go mod init grpc_demo

Writing Proto File and Generating Golang Code

Writing Protocol File

Define a simple Hello service with a Say method:

Filename: proto/hello.proto

syntax = "proto3";

option go_package="/proto";

package Business;

service Hello {
  rpc Say (SayRequest) returns (SayResponse);
}

message SayResponse {
  string Message = 1;
}

message SayRequest {
  string Name = 1;
}
Generating Golang Code
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
proto/hello.proto

For protoc installation, refer to Protocol Buffer Compiler Installation

Implementation Method 1: Traditional Approach

Server Implementation

Filename: v1_server/main.go

package main

import (
  "context"
  "github.com/gone-io/gone/v2"
  "github.com/gone-io/goner"
  goneGrpc "github.com/gone-io/goner/grpc"
  "google.golang.org/grpc"
  "grpc_demo/proto"
  "log"
)

type server struct {
  gone.Flag
  proto.UnimplementedHelloServer // Embed UnimplementedHelloServer
}

// Override the service defined in the protocol
func (s *server) Say(ctx context.Context, in *proto.SayRequest) (*proto.SayResponse, error) {
  log.Printf("Received: %v", in.GetName())
  return &proto.SayResponse{Message: "Hello " + in.GetName()}, nil
}

// Implement the RegisterGrpcServer method of the goneGrpc.Service interface, which will be automatically called when the server starts
func (s *server) RegisterGrpcServer(server *grpc.Server) {
  proto.RegisterHelloServer(server, s)
}

func main() {
  gone.
    Load(&server{}).
    Loads(goner.BaseLoad, goneGrpc.ServerLoad).
    // Start the service
    Serve()
}
Client Implementation

Filename: v1_client/main.go

package main

import (
	"context"
	"fmt"
	"github.com/gone-io/gone/v2"
	"github.com/gone-io/goner"
	gone_grpc "github.com/gone-io/goner/grpc"
	"google.golang.org/grpc"
	"grpc_demo/proto"
	"log"
)

type helloClient struct {
	gone.Flag
	proto.HelloClient // Embed HelloClient

	host string `gone:"config,server.host"`
	port string `gone:"config,server.port"`
}

// Implement the Address method of the gone_grpc.Client interface, which will be automatically called when the client starts
// This method tells the client the address of the gRPC service
func (c *helloClient) Address() string {
	return fmt.Sprintf("%s:%s", c.host, c.port)
}

// Implement the Stub method of the gone_grpc.Client interface, which will be automatically called when the client starts
// Initialize HelloClient in this method
func (c *helloClient) Stub(conn *grpc.ClientConn) {
	c.HelloClient = proto.NewHelloClient(conn)
}

func main() {
	gone.
		Load(&helloClient{}).
		Loads(goner.BaseLoad, gone_grpc.ClientRegisterLoad).
		Run(func(in struct {
			hello *helloClient `gone:"*"` // Inject helloClient in the Run method's parameters
		}) {
			// Call the Say method to send a message to the server
			say, err := in.hello.Say(context.Background(), &proto.SayRequest{Name: "gone"})
			if err != nil {
				log.Printf("er:%v", err)
				return
			}
			log.Printf("say result: %s", say.Message)
		})
}

Implementation Method 2: Gone V2 Provider Mechanism

Gone V2 introduces a powerful Provider mechanism that greatly simplifies the use of gRPC components.

Server Implementation

Filename: v2_server/main.go

package main

import (
	"context"
	"github.com/gone-io/gone/v2"
	goneGrpc "github.com/gone-io/goner/grpc"
	"google.golang.org/grpc"
	"grpc_demo/proto"
	"log"
	"os"
)

type server struct {
	gone.Flag
	proto.UnimplementedHelloServer              // Embed UnimplementedHelloServer
	grpcServer                     *grpc.Server `gone:"*"` // Inject grpc.Server
}

func (s *server) Init() {
	proto.RegisterHelloServer(s.grpcServer, s) // Register service
}

// Say  Override the service defined in the protocol
func (s *server) Say(ctx context.Context, in *proto.SayRequest) (*proto.SayResponse, error) {
	log.Printf("Received: %v", in.GetName())
	return &proto.SayResponse{Message: "Hello " + in.GetName()}, nil
}

func main() {
	// Gone's built-in default configuration component can only read configuration from environment variables
	os.Setenv("GONE_SERVER_GRPC_PORT", "9091")

	gone.
		Load(&server{}).
		Loads(goneGrpc.ServerLoad).
		// Start the service
		Serve()
}
Client Implementation

Filename: v2_client/main.go

package main

import (
	"context"
	"github.com/gone-io/gone/v2"
	gone_grpc "github.com/gone-io/goner/grpc"
	"google.golang.org/grpc"
	"grpc_demo/proto"
	"log"
	"os"
)

type helloClient struct {
	gone.Flag
	proto.HelloClient // Method 1: Embed HelloClient, this component only handles initialization and provides capabilities to third-party components

	// Method 2: Use directly in this component, not providing to third-party components
	//hello *proto.HelloClient

	// config=${config key},address=${service address}; //config has higher priority
	clientConn *grpc.ClientConn `gone:"*,config=grpc.service.hello.address"`

	// config and address can be used together, if config value is not found, fallback to using address
	//clientConn1 *grpc.ClientConn `gone:"*,config=grpc.service.hello.address,address=127.0.0.1:9091"`

	// address can also be used alone, not recommended as it means hardcoding
	//clientConn2 *grpc.ClientConn `gone:"*,address=127.0.0.1:9091"`
}

func (c *helloClient) Init() {
	c.HelloClient = proto.NewHelloClient(c.clientConn)
	//c.hello = &c.HelloClient
}

func main() {
	// Gone's built-in default configuration component can only read configuration from environment variables
	os.Setenv("GONE_GRPC_SERVICE_HELLO_ADDRESS", "127.0.0.1:9091")

	gone.
		Load(&helloClient{}).
		Loads(gone_grpc.ClientRegisterLoad).
		Run(func(in struct {
			hello *helloClient `gone:"*"` // Inject helloClient in the Run method's parameters
		}) {
			// Call the Say method to send a message to the server
			say, err := in.hello.Say(context.Background(), &proto.SayRequest{Name: "gone"})
			if err != nil {
				log.Printf("er:%v", err)
				return
			}
			log.Printf("say result: %s", say.Message)
		})
}

Configuration File

Filename: config/default.properties

# Set grpc service port and host
server.port=9001
server.host=127.0.0.1

# Set grpc service port and host used by the client
server.grpc.port=${server.port}
server.grpc.host=${server.host}

Testing

Running the Server
go run v2_server/main.go  # or v1_server/main.go

The program waits for requests, and the screen displays:

2024-06-19 22:02:41.971|INFO|/Users/jim/works/gone-io/gone/goner/grpc/server.go:84||Register gRPC service *main.server
2024-06-19 22:02:41.971|INFO|/Users/jim/works/gone-io/gone/goner/grpc/server.go:88||gRPC server now listen at 127.0.0.1:9091
Running the Client
go run v2_client/main.go  # or v1_client/main.go

The program exits after execution, and the screen displays:

2024-06-19 22:06:20.713|INFO|/Users/jim/works/gone-io/gone/goner/grpc/client.go:59||register gRPC client *main.helloClient on address 127.0.0.1:9091

2024/06/19 22:06:20 say result: Hello gone

Back in the server window, you can see that the server received the request, with a new log line:

2024/06/19 22:06:08 Received: gone

Comparison of Two Implementation Methods

Traditional Approach

Server Side:

  1. Need to implement the RegisterGrpcServer interface method to register services
  2. Manual management of gRPC service registration process

Client Side:

  1. Need to implement Address and Stub methods to initialize connection
  2. Configuration retrieval is not flexible, address construction logic needs to be written manually
Provider Mechanism

Server Side:

  1. Automatically inject *grpc.Server through tags
  2. Complete service registration in the Init method, conforming to Gone's component lifecycle management

Client Side:

  1. No longer need to implement Address and Stub methods
  2. Support flexible configuration methods, including:
    • Read address from configuration only
    • Use configuration with default address for fallback strategy
    • Direct hardcoded address (not recommended, but supported)

Summary

Gone V2's Provider mechanism greatly improves the gRPC component usage experience:

  1. More Concise Code: Removes unnecessary interface implementations and repetitive template code
  2. Better Alignment with Dependency Injection: Automatically injects required components through tags
  3. More Flexible Configuration: Supports multiple address acquisition strategies, improving code maintainability

Implementation Method 3: Service Registration and Discovery

Gone framework provides service registration and discovery functionality, allowing gRPC services to be deployed and called more flexibly.

Service Registration

The server can register itself with a service discovery center (such as Nacos), allowing clients to access services by service name rather than specific IP address.

Server Implementation
package main

import (
	"context"
	"github.com/gone-io/gone/v2"
	goneGrpc "github.com/gone-io/goner/grpc"
	"github.com/gone-io/goner/nacos" // Import nacos component
	"github.com/gone-io/goner/viper" // Import configuration component
	"google.golang.org/grpc"
	"grpc_demo/proto"
	"log"
)

type server struct {
	gone.Flag
	proto.UnimplementedHelloServer              // Embed UnimplementedHelloServer
	grpcServer                     *grpc.Server `gone:"*"` // Inject grpc.Server
}

func (s *server) Init() {
	proto.RegisterHelloServer(s.grpcServer, s) // Register service
}

// Say Override the service defined in the protocol
func (s *server) Say(ctx context.Context, in *proto.SayRequest) (*proto.SayResponse, error) {
	log.Printf("Received: %v", in.GetName())
	return &proto.SayResponse{Message: "Hello " + in.GetName()}, nil
}

func main() {
	gone.
		NewApp(
			goneGrpc.ServerLoad,
			nacos.RegistryLoad, // Load nacos registry center
			viper.Load,       // Load configuration component
		).
		Load(&server{}).
		// Start the service
		Serve()
}
Server Configuration

The server needs to set the service name and other Nacos-related configurations in the configuration file:

nacos:
  client:
    namespaceId: public
    asyncUpdateService: false
    logLevel: debug
    logDir: ./logs/
  server:
    ipAddr: "127.0.0.1"
    contextPath: /nacos
    port: 8848
    scheme: http

  service:
    group: DEFAULT_GROUP
    clusterName: default

server:
  grpc:
    port: 0  # Use 0 to indicate a random port
    service-name: user-center  # Service name
Service Discovery

The client can obtain the service address from the service discovery center by service name, without hardcoding the service address.

Client Implementation
package main

import (
	"context"
	"github.com/gone-io/gone/v2"
	gone_grpc "github.com/gone-io/goner/grpc"
	"github.com/gone-io/goner/nacos" // Import nacos component
	"github.com/gone-io/goner/viper" // Import configuration component
	"google.golang.org/grpc"
	"grpc_demo/proto"
	"log"
)

type helloClient struct {
	gone.Flag
	proto.HelloClient // Embed HelloClient

	// Connect to the service by service name
	clientConn *grpc.ClientConn `gone:"*,config=grpc.service.hello.address"`
}

func (c *helloClient) Init() {
	c.HelloClient = proto.NewHelloClient(c.clientConn)
}

func main() {
	gone.
		NewApp(
			gone_grpc.ClientRegisterLoad,
			viper.Load,       // Load configuration component
			nacos.RegistryLoad, // Load nacos registry center
		).
		Load(&helloClient{}).
		Run(func(in struct {
			hello *helloClient `gone:"*"` // Inject helloClient in the Run method's parameters
		}) {
			// Call the Say method to send a message to the server
			say, err := in.hello.Say(context.Background(), &proto.SayRequest{Name: "gone"})
			if err != nil {
				log.Printf("err: %v", err)
				return
			}
			log.Printf("say result: %s", say.Message)
		})
}
Client Configuration

The client needs to set the service name and other Nacos-related configurations in the configuration file:

nacos:
  client:
    namespaceId: public
    asyncUpdateService: false
    logLevel: debug
    logDir: ./logs/
  server:
    ipAddr: "127.0.0.1"
    contextPath: /nacos
    port: 8848
    scheme: http

grpc:
  service:
    hello:
      address: user-center  # Service name, not a specific IP address
Advantages of Service Registration and Discovery
  1. Service Decoupling: The client does not need to know the specific address of the server, only the service name
  2. Dynamic Scaling: Service instances can be dynamically added or reduced, and the client automatically perceives this
  3. Load Balancing: When there are multiple service instances, the client can automatically perform load balancing
  4. High Availability: When a service instance fails, the client can automatically switch to other available instances
  5. Unified Management: All services can be uniformly managed and monitored in the service discovery center

Documentation

Overview

Package grpc is a generated GoMock package.

Package grpc is a generated GoMock package.

Package grpc is a generated GoMock package.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ClientLoad added in v1.0.9

func ClientLoad(loader gone.Loader) error

ClientLoad @deprecated use ClientRegisterLoad instead

func ClientRegisterLoad

func ClientRegisterLoad(loader gone.Loader) error

ClientRegisterLoad load client register

func Load added in v1.0.9

func Load(loader gone.Loader) error

Load all @deprecated use ServerLoad and ClientRegisterLoad instead

func NewRegister

func NewRegister() gone.Goner

func NewResolverBuilder added in v1.0.9

func NewResolverBuilder(discovery g.ServiceDiscovery, logger gone.Logger) resolver.Builder

func ServerLoad

func ServerLoad(loader gone.Loader) error

ServerLoad load server

Types

type Client

type Client interface {
	Address() string
	Stub(conn *grpc.ClientConn)
}

type MockAddr added in v1.0.9

type MockAddr struct {
	// contains filtered or unexported fields
}

MockAddr is a mock of Addr interface.

func NewMockAddr added in v1.0.9

func NewMockAddr(ctrl *gomock.Controller) *MockAddr

NewMockAddr creates a new mock instance.

func (*MockAddr) EXPECT added in v1.0.9

func (m *MockAddr) EXPECT() *MockAddrMockRecorder

EXPECT returns an object that allows the caller to indicate expected use.

func (*MockAddr) Network added in v1.0.9

func (m *MockAddr) Network() string

Network mocks base method.

func (*MockAddr) String added in v1.0.9

func (m *MockAddr) String() string

String mocks base method.

type MockAddrMockRecorder added in v1.0.9

type MockAddrMockRecorder struct {
	// contains filtered or unexported fields
}

MockAddrMockRecorder is the mock recorder for MockAddr.

func (*MockAddrMockRecorder) Network added in v1.0.9

func (mr *MockAddrMockRecorder) Network() *gomock.Call

Network indicates an expected call of Network.

func (*MockAddrMockRecorder) String added in v1.0.9

func (mr *MockAddrMockRecorder) String() *gomock.Call

String indicates an expected call of String.

type MockClient added in v1.0.9

type MockClient struct {
	// contains filtered or unexported fields
}

MockClient is a mock of Client interface.

func NewMockClient added in v1.0.9

func NewMockClient(ctrl *gomock.Controller) *MockClient

NewMockClient creates a new mock instance.

func (*MockClient) Address added in v1.0.9

func (m *MockClient) Address() string

Address mocks base method.

func (*MockClient) EXPECT added in v1.0.9

func (m *MockClient) EXPECT() *MockClientMockRecorder

EXPECT returns an object that allows the caller to indicate expected use.

func (*MockClient) Stub added in v1.0.9

func (m *MockClient) Stub(conn *grpc.ClientConn)

Stub mocks base method.

type MockClientConn added in v1.0.9

type MockClientConn struct {
	// contains filtered or unexported fields
}

MockClientConn is a mock of ClientConn interface.

func NewMockClientConn added in v1.0.9

func NewMockClientConn(ctrl *gomock.Controller) *MockClientConn

NewMockClientConn creates a new mock instance.

func (*MockClientConn) EXPECT added in v1.0.9

EXPECT returns an object that allows the caller to indicate expected use.

func (*MockClientConn) NewAddress added in v1.0.9

func (m *MockClientConn) NewAddress(addresses []resolver.Address)

NewAddress mocks base method.

func (*MockClientConn) ParseServiceConfig added in v1.0.9

func (m *MockClientConn) ParseServiceConfig(serviceConfigJSON string) *serviceconfig.ParseResult

ParseServiceConfig mocks base method.

func (*MockClientConn) ReportError added in v1.0.9

func (m *MockClientConn) ReportError(arg0 error)

ReportError mocks base method.

func (*MockClientConn) UpdateState added in v1.0.9

func (m *MockClientConn) UpdateState(arg0 resolver.State) error

UpdateState mocks base method.

type MockClientConnMockRecorder added in v1.0.9

type MockClientConnMockRecorder struct {
	// contains filtered or unexported fields
}

MockClientConnMockRecorder is the mock recorder for MockClientConn.

func (*MockClientConnMockRecorder) NewAddress added in v1.0.9

func (mr *MockClientConnMockRecorder) NewAddress(addresses any) *gomock.Call

NewAddress indicates an expected call of NewAddress.

func (*MockClientConnMockRecorder) ParseServiceConfig added in v1.0.9

func (mr *MockClientConnMockRecorder) ParseServiceConfig(serviceConfigJSON any) *gomock.Call

ParseServiceConfig indicates an expected call of ParseServiceConfig.

func (*MockClientConnMockRecorder) ReportError added in v1.0.9

func (mr *MockClientConnMockRecorder) ReportError(arg0 any) *gomock.Call

ReportError indicates an expected call of ReportError.

func (*MockClientConnMockRecorder) UpdateState added in v1.0.9

func (mr *MockClientConnMockRecorder) UpdateState(arg0 any) *gomock.Call

UpdateState indicates an expected call of UpdateState.

type MockClientMockRecorder added in v1.0.9

type MockClientMockRecorder struct {
	// contains filtered or unexported fields
}

MockClientMockRecorder is the mock recorder for MockClient.

func (*MockClientMockRecorder) Address added in v1.0.9

func (mr *MockClientMockRecorder) Address() *gomock.Call

Address indicates an expected call of Address.

func (*MockClientMockRecorder) Stub added in v1.0.9

func (mr *MockClientMockRecorder) Stub(conn any) *gomock.Call

Stub indicates an expected call of Stub.

type MockConn added in v1.0.9

type MockConn struct {
	// contains filtered or unexported fields
}

MockConn is a mock of Conn interface.

func NewMockConn added in v1.0.9

func NewMockConn(ctrl *gomock.Controller) *MockConn

NewMockConn creates a new mock instance.

func (*MockConn) Close added in v1.0.9

func (m *MockConn) Close() error

Close mocks base method.

func (*MockConn) EXPECT added in v1.0.9

func (m *MockConn) EXPECT() *MockConnMockRecorder

EXPECT returns an object that allows the caller to indicate expected use.

func (*MockConn) LocalAddr added in v1.0.9

func (m *MockConn) LocalAddr() net.Addr

LocalAddr mocks base method.

func (*MockConn) Read added in v1.0.9

func (m *MockConn) Read(b []byte) (int, error)

Read mocks base method.

func (*MockConn) RemoteAddr added in v1.0.9

func (m *MockConn) RemoteAddr() net.Addr

RemoteAddr mocks base method.

func (*MockConn) SetDeadline added in v1.0.9

func (m *MockConn) SetDeadline(t time.Time) error

SetDeadline mocks base method.

func (*MockConn) SetReadDeadline added in v1.0.9

func (m *MockConn) SetReadDeadline(t time.Time) error

SetReadDeadline mocks base method.

func (*MockConn) SetWriteDeadline added in v1.0.9

func (m *MockConn) SetWriteDeadline(t time.Time) error

SetWriteDeadline mocks base method.

func (*MockConn) Write added in v1.0.9

func (m *MockConn) Write(b []byte) (int, error)

Write mocks base method.

type MockConnMockRecorder added in v1.0.9

type MockConnMockRecorder struct {
	// contains filtered or unexported fields
}

MockConnMockRecorder is the mock recorder for MockConn.

func (*MockConnMockRecorder) Close added in v1.0.9

func (mr *MockConnMockRecorder) Close() *gomock.Call

Close indicates an expected call of Close.

func (*MockConnMockRecorder) LocalAddr added in v1.0.9

func (mr *MockConnMockRecorder) LocalAddr() *gomock.Call

LocalAddr indicates an expected call of LocalAddr.

func (*MockConnMockRecorder) Read added in v1.0.9

func (mr *MockConnMockRecorder) Read(b any) *gomock.Call

Read indicates an expected call of Read.

func (*MockConnMockRecorder) RemoteAddr added in v1.0.9

func (mr *MockConnMockRecorder) RemoteAddr() *gomock.Call

RemoteAddr indicates an expected call of RemoteAddr.

func (*MockConnMockRecorder) SetDeadline added in v1.0.9

func (mr *MockConnMockRecorder) SetDeadline(t any) *gomock.Call

SetDeadline indicates an expected call of SetDeadline.

func (*MockConnMockRecorder) SetReadDeadline added in v1.0.9

func (mr *MockConnMockRecorder) SetReadDeadline(t any) *gomock.Call

SetReadDeadline indicates an expected call of SetReadDeadline.

func (*MockConnMockRecorder) SetWriteDeadline added in v1.0.9

func (mr *MockConnMockRecorder) SetWriteDeadline(t any) *gomock.Call

SetWriteDeadline indicates an expected call of SetWriteDeadline.

func (*MockConnMockRecorder) Write added in v1.0.9

func (mr *MockConnMockRecorder) Write(b any) *gomock.Call

Write indicates an expected call of Write.

type MockListener added in v1.0.9

type MockListener struct {
	// contains filtered or unexported fields
}

MockListener is a mock of Listener interface.

func NewMockListener added in v1.0.9

func NewMockListener(ctrl *gomock.Controller) *MockListener

NewMockListener creates a new mock instance.

func (*MockListener) Accept added in v1.0.9

func (m *MockListener) Accept() (net.Conn, error)

Accept mocks base method.

func (*MockListener) Addr added in v1.0.9

func (m *MockListener) Addr() net.Addr

Addr mocks base method.

func (*MockListener) Close added in v1.0.9

func (m *MockListener) Close() error

Close mocks base method.

func (*MockListener) EXPECT added in v1.0.9

EXPECT returns an object that allows the caller to indicate expected use.

type MockListenerMockRecorder added in v1.0.9

type MockListenerMockRecorder struct {
	// contains filtered or unexported fields
}

MockListenerMockRecorder is the mock recorder for MockListener.

func (*MockListenerMockRecorder) Accept added in v1.0.9

func (mr *MockListenerMockRecorder) Accept() *gomock.Call

Accept indicates an expected call of Accept.

func (*MockListenerMockRecorder) Addr added in v1.0.9

func (mr *MockListenerMockRecorder) Addr() *gomock.Call

Addr indicates an expected call of Addr.

func (*MockListenerMockRecorder) Close added in v1.0.9

func (mr *MockListenerMockRecorder) Close() *gomock.Call

Close indicates an expected call of Close.

type MockService added in v1.0.9

type MockService struct {
	// contains filtered or unexported fields
}

MockService is a mock of Service interface.

func NewMockService added in v1.0.9

func NewMockService(ctrl *gomock.Controller) *MockService

NewMockService creates a new mock instance.

func (*MockService) EXPECT added in v1.0.9

func (m *MockService) EXPECT() *MockServiceMockRecorder

EXPECT returns an object that allows the caller to indicate expected use.

func (*MockService) RegisterGrpcServer added in v1.0.9

func (m *MockService) RegisterGrpcServer(server *grpc.Server)

RegisterGrpcServer mocks base method.

type MockServiceMockRecorder added in v1.0.9

type MockServiceMockRecorder struct {
	// contains filtered or unexported fields
}

MockServiceMockRecorder is the mock recorder for MockService.

func (*MockServiceMockRecorder) RegisterGrpcServer added in v1.0.9

func (mr *MockServiceMockRecorder) RegisterGrpcServer(server any) *gomock.Call

RegisterGrpcServer indicates an expected call of RegisterGrpcServer.

type Service

type Service interface {
	RegisterGrpcServer(server *grpc.Server)
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL