package grpc import ( "context" "fmt" "log" "sync" "time" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/keepalive" // 使用生成的 proto 代码(通过 go.mod replace 指向本地目录,不修改 grpc 目录) userv1 "grpc/user/userv1" ) var ( userClientOnce sync.Once userClient *UserClient ) type UserClient struct { conn *grpc.ClientConn addr string client userv1.UserClient } // NewUserClient 创建用户服务 gRPC 客户端 func NewUserClient(addr string) (*UserClient, error) { if addr == "" { return nil, fmt.Errorf("gRPC server address is empty") } var err error userClientOnce.Do(func() { opts := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithKeepaliveParams(keepalive.ClientParameters{ Time: 10 * time.Second, Timeout: 3 * time.Second, PermitWithoutStream: true, }), } conn, dialErr := grpc.Dial(addr, opts...) if dialErr != nil { err = fmt.Errorf("failed to connect to gRPC server %s: %w", addr, dialErr) return } client := userv1.NewUserClient(conn) userClient = &UserClient{ conn: conn, addr: addr, client: client, } log.Printf("gRPC user client connected to %s", addr) }) if err != nil { return nil, err } return userClient, nil } // SimpleListAllUser 调用 SimpleListAllUser gRPC 方法 func (c *UserClient) SimpleListAllUser(ctx context.Context, keyword string) (*userv1.SimpleListAllUserResp, error) { req := &userv1.SimpleListAllUserReq{ Keyword: keyword, } resp, err := c.client.SimpleListAllUser(ctx, req) if err != nil { return nil, fmt.Errorf("gRPC SimpleListAllUser failed: %w", err) } return resp, nil } // Close 关闭连接 func (c *UserClient) Close() error { if c.conn != nil { return c.conn.Close() } return nil } // GetConn 获取 gRPC 连接(用于直接调用生成的客户端) func (c *UserClient) GetConn() *grpc.ClientConn { return c.conn }