package grpc import ( "context" "fmt" "log" "sync" "time" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/keepalive" ) var ( userClientOnce sync.Once userClient *UserClient ) // AdminSimpleInfo 临时结构,等 proto 生成后会被替换 type AdminSimpleInfo struct { Id int32 Username string Realname string } // SimpleListAllUserResp 临时结构,等 proto 生成后会被替换 type SimpleListAllUserResp struct { List []*AdminSimpleInfo } type UserClient struct { conn *grpc.ClientConn addr string client interface{} // 临时使用 interface{},等 proto 生成后改为 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 } // TODO: 等 proto 文件生成后,取消注释下面的代码 // client := userv1.NewUserClient(conn) userClient = &UserClient{ conn: conn, addr: addr, client: nil, // 临时设为 nil,等 proto 生成后使用 userv1.NewUserClient(conn) } log.Printf("gRPC user client connected to %s (proto code not generated yet)", addr) }) if err != nil { return nil, err } return userClient, nil } // SimpleListAllUser 调用 SimpleListAllUser gRPC 方法 // 注意:此方法需要 proto 生成的代码才能正常工作 // 请先运行: cd grpc && make generate func (c *UserClient) SimpleListAllUser(ctx context.Context, keyword string) (*SimpleListAllUserResp, error) { // TODO: 等 proto 文件生成后,取消注释下面的代码并删除临时实现 // 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 // 临时实现:返回错误提示需要生成 proto return nil, fmt.Errorf("proto code not generated, please run 'cd grpc && make generate' first, then rebuild with -tags proto_generated") } // 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 }