[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6H9VYVVDQ07JDKMSR3WM337":3,"skill-same:01M6H9VYVVDQ07JDKMSR3WM337":55},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":26,"linkOnly":27,"markdownContent":28,"markdownBody":29,"frontMatter":30,"refName":33,"commitSha":34,"skillDirectory":35,"forksCount":14,"repositoryHtmlUrl":36,"repositoryHomepageUrl":6,"ownerHtmlUrl":37,"ownerBlogUrl":38,"ownerDescription":39,"updatedAt":40,"install":41,"resources":54},"01M6H9VYVVDQ07JDKMSR3WM337","grpc",null,"gRPC framework best practices and implementation","NeuralBlitz\u002FMito","NeuralBlitz","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F79354388?v=4","01M6H8T2TFH477HRS0KTSTKR2E","David Riggs","01M6H8T2YQQDXPYM092P670Z21",0,"MIT","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fgrpc\u002FSKILL.md",[],[5,19,20,21,22,23,24,25],"design","best practices","framework","api","opencode","implementation","api-design","2026-11-10 10:12:30",false,"---\nname: grpc\ndescription: gRPC framework best practices and implementation\nlicense: MIT\ncompatibility: opencode\nmetadata:\n  audience: developers\n  category: api-design\n---\n## What I do\n- Define Protocol Buffer schemas\n- Implement gRPC services\n- Handle streaming\n- Implement authentication\n- Handle errors properly\n- Manage versioning\n- Test gRPC services\n- Scale gRPC deployments\n\n## When to use me\nWhen implementing gRPC services or working with Protocol Buffers.\n\n## Protocol Buffer Definition\n```protobuf\nsyntax = \"proto3\";\n\npackage user.v1;\n\noption go_package = \"github.com\u002Fcompany\u002Fapi\u002Fuser\u002Fv1\";\n\nimport \"google\u002Fprotobuf\u002Ftimestamp.proto\";\nimport \"google\u002Fprotobuf\u002Fempty.proto\";\n\n\n\u002F\u002F Service definition\nservice UserService {\n  \u002F\u002F Unary RPC\n  rpc GetUser(GetUserRequest) returns (User);\n  \n  \u002F\u002F Server streaming\n  rpc ListUsers(ListUsersRequest) returns (stream User);\n  \n  \u002F\u002F Client streaming\n  rpc CreateUsers(stream CreateUserRequest) returns (CreateUsersResponse);\n  \n  \u002F\u002F Bidirectional streaming\n  rpc StreamUserUpdates(stream UserUpdateRequest) returns (stream User);\n  \n  \u002F\u002F Health check\n  rpc HealthCheck(google.protobuf.Empty) returns (HealthCheckResponse);\n}\n\n\n\u002F\u002F Message types\nmessage GetUserRequest {\n  string user_id = 1;\n}\n\nmessage User {\n  string id = 1;\n  string email = 2;\n  string name = 3;\n  UserStatus status = 4;\n  google.protobuf.Timestamp created_at = 5;\n  google.protobuf.Timestamp updated_at = 6;\n}\n\nenum UserStatus {\n  USER_STATUS_UNSPECIFIED = 0;\n  USER_STATUS_ACTIVE = 1;\n  USER_STATUS_INACTIVE = 2;\n  USER_STATUS_SUSPENDED = 3;\n}\n\nmessage ListUsersRequest {\n  int32 page_size = 1;\n  string page_token = 2;\n  UserStatus status_filter = 3;\n}\n\nmessage CreateUserRequest {\n  string email = 1;\n  string name = 2;\n  string password = 3;\n}\n\nmessage CreateUsersResponse {\n  repeated User users = 1;\n  int32 failed_count = 2;\n}\n\nmessage UserUpdateRequest {\n  string user_id = 1;\n  string name = 2;\n}\n\nmessage HealthCheckResponse {\n  bool healthy = 1;\n  string version = 2;\n}\n```\n\n## Go gRPC Server\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"net\"\n\n\t\"google.golang.org\u002Fgrpc\"\n\t\"google.golang.org\u002Fgrpc\u002Fcodes\"\n\t\"google.golang.org\u002Fgrpc\u002Fcredentials\"\n\t\"google.golang.org\u002Fgrpc\u002Fmetadata\"\n\t\"google.golang.org\u002Fgrpc\u002Fstatus\"\n\t\"google.golang.org\u002Fprotobuf\u002Ftypes\u002Fknown\u002Ftimestamppb\"\n\n\tpb \"github.com\u002Fcompany\u002Fapi\u002Fuser\u002Fv1\"\n)\n\ntype UserServer struct {\n\tpb.UnimplementedUserServiceServer\n\tuserStore UserStore\n}\n\ntype UserStore interface {\n\tGetUser(ctx context.Context, id string) (*pb.User, error)\n\tListUsers(ctx context.Context, filter *pb.UserStatus, limit int) ([]*pb.User, error)\n\tCreateUser(ctx context.Context, user *pb.User) error\n}\n\nfunc NewUserServer(store UserStore) *UserServer {\n\treturn &UserServer{userStore: store}\n}\n\nfunc (s *UserServer) GetUser(\n\tctx context.Context,\n\treq *pb.GetUserRequest,\n) (*pb.User, error) {\n\t\u002F\u002F Extract metadata for logging\n\tmd, ok := metadata.FromIncomingContext(ctx)\n\tif ok {\n\t\tlog.Printf(\"GetUser request: user_id=%s, from=%v\", req.UserId, md.Get(\"x-forwarded-for\"))\n\t}\n\n\t\u002F\u002F Validate request\n\tif req.UserId == \"\" {\n\t\treturn nil, status.Error(codes.InvalidArgument, \"user_id is required\")\n\t}\n\n\t\u002F\u002F Fetch user\n\tuser, err := s.userStore.GetUser(ctx, req.UserId)\n\tif err != nil {\n\t\treturn nil, status.Errorf(codes.NotFound, \"user not found: %s\", err)\n\t}\n\n\treturn user, nil\n}\n\nfunc (s *UserServer) ListUsers(\n\treq *pb.ListUsersRequest,\n\tstream pb.UserService_ListUsersServer,\n) error {\n\tctx := stream.Context()\n\n\t\u002F\u002F Parse pagination\n\tpageSize := int(req.PageSize)\n\tif pageSize \u003C= 0 {\n\t\tpageSize = 10\n\t}\n\tif pageSize > 100 {\n\t\tpageSize = 100\n\t}\n\n\tusers, err := s.userStore.ListUsers(ctx, req.StatusFilter, pageSize)\n\tif err != nil {\n\t\treturn status.Errorf(codes.Internal, \"failed to list users: %v\", err)\n\t}\n\n\t\u002F\u002F Stream users to client\n\tfor _, user := range users {\n\t\tif err := stream.Send(user); err != nil {\n\t\t\treturn status.Errorf(codes.Internal, \"failed to send user: %v\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (s *UserService) CreateUsers(\n\tstream pb.UserService_CreateUsersServer,\n) error {\n\tctx := stream.Context()\n\tvar users []*pb.User\n\tvar failedCount int32\n\n\tfor {\n\t\treq, err := stream.Recv()\n\t\tif err != nil {\n\t\t\tif err.Error() == \"EOF\" {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn status.Errorf(codes.Internal, \"failed to receive request: %v\", err)\n\t\t}\n\n\t\tuser := &pb.User{\n\t\t\tEmail:     req.Email,\n\t\t\tName:      req.Name,\n\t\t\tStatus:    pb.UserStatus_USER_STATUS_ACTIVE,\n\t\t\tCreatedAt: timestamppb.Now(),\n\t\t}\n\n\t\tif err := s.userStore.CreateUser(ctx, user); err != nil {\n\t\t\tfailedCount++\n\t\t\tlog.Printf(\"Failed to create user: %v\", err)\n\t\t\tcontinue\n\t\t}\n\n\t\tusers = append(users, user)\n\t}\n\n\treturn stream.SendAndClose(&pb.CreateUsersResponse{\n\t\tUsers:       users,\n\t\tFailedCount: failedCount,\n\t})\n}\n\nfunc (s *UserServer) StreamUserUpdates(\n\tstream pb.UserService_StreamUserUpdatesServer,\n) error {\n\tctx := stream.Context()\n\n\tfor {\n\t\tselect {\n\t\tcase \u003C-ctx.Done():\n\t\t\treturn ctx.Err()\n\t\tdefault:\n\t\t\treq, err := stream.Recv()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tuser, err := s.userStore.GetUser(ctx, req.UserId)\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif err := stream.Send(user); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n}\n\n\u002F\u002F Server reflection for debugging\nfunc init() {\n\t\u002F\u002F Enable reflection\n\t\u002F\u002F reflection.Register(grpcServer)\n}\n```\n\n## gRPC Client\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"time\"\n\n\t\"google.golang.org\u002Fgrpc\"\n\t\"google.golang.org\u002Fgrpc\u002Fcredentials\u002Finsecure\"\n\t\"google.golang.org\u002Fgrpc\u002Fmetadata\"\n\n\tpb \"github.com\u002Fcompany\u002Fapi\u002Fuser\u002Fv1\"\n)\n\ntype UserClient struct {\n\tconn   *grpc.ClientConn\n\tclient pb.UserServiceClient\n}\n\nfunc NewUserClient(addr string) (*UserClient, error) {\n\tconn, err := grpc.Dial(\n\t\taddr,\n\t\tgrpc.WithTransportCredentials(insecure.NewCredentials()),\n\t\tgrpc.WithUnaryInterceptor(loggingInterceptor),\n\t\tgrpc.WithStreamInterceptor(streamLoggingInterceptor),\n\t)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &UserClient{\n\t\tconn:   conn,\n\t\tclient: pb.NewUserServiceClient(conn),\n\t}, nil\n}\n\nfunc (c *UserClient) GetUser(ctx context.Context, userId string) (*pb.User, error) {\n\t\u002F\u002F Add metadata for tracing\n\tctx = metadata.AppendToOutgoingContext(ctx, \"x-request-id\", \"req-123\")\n\n\tctx, cancel := context.WithTimeout(ctx, 5*time.Second)\n\tdefer cancel()\n\n\treturn c.client.GetUser(ctx, &pb.GetUserRequest{\n\t\tUserId: userId,\n\t})\n}\n\nfunc (c *UserClient) ListActiveUsers(ctx context.Context) ([]*pb.User, error) {\n\tctx, cancel := context.WithTimeout(ctx, 30*time.Second)\n\tdefer cancel()\n\n\tstream, err := c.client.ListUsers(ctx, &pb.ListUsersRequest{\n\t\tPageSize:  100,\n\t\tStatusFilter: pb.UserStatus_USER_STATUS_ACTIVE,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar users []*pb.User\n\tfor {\n\t\tuser, err := stream.Recv()\n\t\tif err != nil {\n\t\t\tif err.Error() == \"EOF\" {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tusers = append(users, user)\n\t}\n\n\treturn users, nil\n}\n\nfunc (c *UserClient) Close() error {\n\treturn c.conn.Close()\n}\n\n\u002F\u002F Interceptors\nfunc loggingInterceptor(\n\tctx context.Context,\n\tmethod string,\n\treq, reply interface{},\n\tcc *grpc.ClientConn,\n\tinvoker grpc.UnaryInvoker,\n\topts ...grpc.CallOption,\n) error {\n\tstart := time.Now()\n\t\n\terr := invoker(ctx, method, req, reply, cc, opts...)\n\t\n\tlog.Printf(\"gRPC call: %s, duration: %v, error: %v\",\n\t\tmethod, time.Since(start), err)\n\t\n\treturn err\n}\n\nfunc streamLoggingInterceptor(\n\tctx context.Context,\n\tdesc *grpc.StreamDesc,\n\tcc *grpc.ClientConn,\n\tmethod string,\n\tstream grpc.ClientStream,\n\topts ...grpc.CallOption,\n) error {\n\tstart := time.Now()\n\t\n\terr := stream.RecvMsg(nil)\n\t\n\tlog.Printf(\"gRPC stream: %s, duration: %v, error: %v\",\n\t\tmethod, time.Since(start), err)\n\t\n\treturn err\n}\n```\n\n## Error Handling\n```go\npackage status\n\nimport (\n\t\"google.golang.org\u002Fgrpc\u002Fcodes\"\n\t\"google.golang.org\u002Fgrpc\u002Fstatus\"\n)\n\n\u002F\u002F Custom error codes\nconst (\n\tErrCodeUserNotFound = \"USER_NOT_FOUND\"\n\tErrCodeInvalidInput = \"INVALID_INPUT\"\n\tErrCodeUnauthorized = \"UNAUTHORIZED\"\n)\n\nfunc UserNotFound(id string) error {\n\treturn status.Errorf(codes.NotFound, \"user not found: %s\", id)\n}\n\nfunc InvalidInput(field, reason string) error {\n\treturn status.Errorf(codes.InvalidArgument, \"invalid %s: %s\", field, reason)\n}\n\nfunc Unauthorized(reason string) error {\n\treturn status.Errorf(codes.Unauthenticated, \"unauthorized: %s\", reason)\n}\n```\n\n## gRPC Best Practices\n```\n1. Use Protocol Buffers for schema\n   - Define contracts explicitly\n   - Enable backwards compatibility\n\n2. Handle errors properly\n   - Use gRPC status codes\n   - Include error details\n\n3. Implement interceptors\n   - Logging, auth, metrics\n\n4. Use streaming appropriately\n   - Server streaming for lists\n   - Bidirectional for real-time\n\n5. Set timeouts\n   - Always use context with timeout\n\n6. Enable reflection\n   - For debugging and tools\n\n7. Version your APIs\n   - Include version in package name\n   - Support multiple versions\n\n8. Use proper authentication\n   - Token-based or mTLS\n\n9. Monitor and trace\n   - Add interceptors for metrics\n   - Use OpenTelemetry\n\n10. Test thoroughly\n    - Unit tests with mock stores\n    - Integration tests\n```\n","## What I do\n- Define Protocol Buffer schemas\n- Implement gRPC services\n- Handle streaming\n- Implement authentication\n- Handle errors properly\n- Manage versioning\n- Test gRPC services\n- Scale gRPC deployments\n\n## When to use me\nWhen implementing gRPC services or working with Protocol Buffers.\n\n## Protocol Buffer Definition\n```protobuf\nsyntax = \"proto3\";\n\npackage user.v1;\n\noption go_package = \"github.com\u002Fcompany\u002Fapi\u002Fuser\u002Fv1\";\n\nimport \"google\u002Fprotobuf\u002Ftimestamp.proto\";\nimport \"google\u002Fprotobuf\u002Fempty.proto\";\n\n\n\u002F\u002F Service definition\nservice UserService {\n  \u002F\u002F Unary RPC\n  rpc GetUser(GetUserRequest) returns (User);\n  \n  \u002F\u002F Server streaming\n  rpc ListUsers(ListUsersRequest) returns (stream User);\n  \n  \u002F\u002F Client streaming\n  rpc CreateUsers(stream CreateUserRequest) returns (CreateUsersResponse);\n  \n  \u002F\u002F Bidirectional streaming\n  rpc StreamUserUpdates(stream UserUpdateRequest) returns (stream User);\n  \n  \u002F\u002F Health check\n  rpc HealthCheck(google.protobuf.Empty) returns (HealthCheckResponse);\n}\n\n\n\u002F\u002F Message types\nmessage GetUserRequest {\n  string user_id = 1;\n}\n\nmessage User {\n  string id = 1;\n  string email = 2;\n  string name = 3;\n  UserStatus status = 4;\n  google.protobuf.Timestamp created_at = 5;\n  google.protobuf.Timestamp updated_at = 6;\n}\n\nenum UserStatus {\n  USER_STATUS_UNSPECIFIED = 0;\n  USER_STATUS_ACTIVE = 1;\n  USER_STATUS_INACTIVE = 2;\n  USER_STATUS_SUSPENDED = 3;\n}\n\nmessage ListUsersRequest {\n  int32 page_size = 1;\n  string page_token = 2;\n  UserStatus status_filter = 3;\n}\n\nmessage CreateUserRequest {\n  string email = 1;\n  string name = 2;\n  string password = 3;\n}\n\nmessage CreateUsersResponse {\n  repeated User users = 1;\n  int32 failed_count = 2;\n}\n\nmessage UserUpdateRequest {\n  string user_id = 1;\n  string name = 2;\n}\n\nmessage HealthCheckResponse {\n  bool healthy = 1;\n  string version = 2;\n}\n```\n\n## Go gRPC Server\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"net\"\n\n\t\"google.golang.org\u002Fgrpc\"\n\t\"google.golang.org\u002Fgrpc\u002Fcodes\"\n\t\"google.golang.org\u002Fgrpc\u002Fcredentials\"\n\t\"google.golang.org\u002Fgrpc\u002Fmetadata\"\n\t\"google.golang.org\u002Fgrpc\u002Fstatus\"\n\t\"google.golang.org\u002Fprotobuf\u002Ftypes\u002Fknown\u002Ftimestamppb\"\n\n\tpb \"github.com\u002Fcompany\u002Fapi\u002Fuser\u002Fv1\"\n)\n\ntype UserServer struct {\n\tpb.UnimplementedUserServiceServer\n\tuserStore UserStore\n}\n\ntype UserStore interface {\n\tGetUser(ctx context.Context, id string) (*pb.User, error)\n\tListUsers(ctx context.Context, filter *pb.UserStatus, limit int) ([]*pb.User, error)\n\tCreateUser(ctx context.Context, user *pb.User) error\n}\n\nfunc NewUserServer(store UserStore) *UserServer {\n\treturn &UserServer{userStore: store}\n}\n\nfunc (s *UserServer) GetUser(\n\tctx context.Context,\n\treq *pb.GetUserRequest,\n) (*pb.User, error) {\n\t\u002F\u002F Extract metadata for logging\n\tmd, ok := metadata.FromIncomingContext(ctx)\n\tif ok {\n\t\tlog.Printf(\"GetUser request: user_id=%s, from=%v\", req.UserId, md.Get(\"x-forwarded-for\"))\n\t}\n\n\t\u002F\u002F Validate request\n\tif req.UserId == \"\" {\n\t\treturn nil, status.Error(codes.InvalidArgument, \"user_id is required\")\n\t}\n\n\t\u002F\u002F Fetch user\n\tuser, err := s.userStore.GetUser(ctx, req.UserId)\n\tif err != nil {\n\t\treturn nil, status.Errorf(codes.NotFound, \"user not found: %s\", err)\n\t}\n\n\treturn user, nil\n}\n\nfunc (s *UserServer) ListUsers(\n\treq *pb.ListUsersRequest,\n\tstream pb.UserService_ListUsersServer,\n) error {\n\tctx := stream.Context()\n\n\t\u002F\u002F Parse pagination\n\tpageSize := int(req.PageSize)\n\tif pageSize \u003C= 0 {\n\t\tpageSize = 10\n\t}\n\tif pageSize > 100 {\n\t\tpageSize = 100\n\t}\n\n\tusers, err := s.userStore.ListUsers(ctx, req.StatusFilter, pageSize)\n\tif err != nil {\n\t\treturn status.Errorf(codes.Internal, \"failed to list users: %v\", err)\n\t}\n\n\t\u002F\u002F Stream users to client\n\tfor _, user := range users {\n\t\tif err := stream.Send(user); err != nil {\n\t\t\treturn status.Errorf(codes.Internal, \"failed to send user: %v\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (s *UserService) CreateUsers(\n\tstream pb.UserService_CreateUsersServer,\n) error {\n\tctx := stream.Context()\n\tvar users []*pb.User\n\tvar failedCount int32\n\n\tfor {\n\t\treq, err := stream.Recv()\n\t\tif err != nil {\n\t\t\tif err.Error() == \"EOF\" {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn status.Errorf(codes.Internal, \"failed to receive request: %v\", err)\n\t\t}\n\n\t\tuser := &pb.User{\n\t\t\tEmail:     req.Email,\n\t\t\tName:      req.Name,\n\t\t\tStatus:    pb.UserStatus_USER_STATUS_ACTIVE,\n\t\t\tCreatedAt: timestamppb.Now(),\n\t\t}\n\n\t\tif err := s.userStore.CreateUser(ctx, user); err != nil {\n\t\t\tfailedCount++\n\t\t\tlog.Printf(\"Failed to create user: %v\", err)\n\t\t\tcontinue\n\t\t}\n\n\t\tusers = append(users, user)\n\t}\n\n\treturn stream.SendAndClose(&pb.CreateUsersResponse{\n\t\tUsers:       users,\n\t\tFailedCount: failedCount,\n\t})\n}\n\nfunc (s *UserServer) StreamUserUpdates(\n\tstream pb.UserService_StreamUserUpdatesServer,\n) error {\n\tctx := stream.Context()\n\n\tfor {\n\t\tselect {\n\t\tcase \u003C-ctx.Done():\n\t\t\treturn ctx.Err()\n\t\tdefault:\n\t\t\treq, err := stream.Recv()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tuser, err := s.userStore.GetUser(ctx, req.UserId)\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif err := stream.Send(user); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n}\n\n\u002F\u002F Server reflection for debugging\nfunc init() {\n\t\u002F\u002F Enable reflection\n\t\u002F\u002F reflection.Register(grpcServer)\n}\n```\n\n## gRPC Client\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"time\"\n\n\t\"google.golang.org\u002Fgrpc\"\n\t\"google.golang.org\u002Fgrpc\u002Fcredentials\u002Finsecure\"\n\t\"google.golang.org\u002Fgrpc\u002Fmetadata\"\n\n\tpb \"github.com\u002Fcompany\u002Fapi\u002Fuser\u002Fv1\"\n)\n\ntype UserClient struct {\n\tconn   *grpc.ClientConn\n\tclient pb.UserServiceClient\n}\n\nfunc NewUserClient(addr string) (*UserClient, error) {\n\tconn, err := grpc.Dial(\n\t\taddr,\n\t\tgrpc.WithTransportCredentials(insecure.NewCredentials()),\n\t\tgrpc.WithUnaryInterceptor(loggingInterceptor),\n\t\tgrpc.WithStreamInterceptor(streamLoggingInterceptor),\n\t)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &UserClient{\n\t\tconn:   conn,\n\t\tclient: pb.NewUserServiceClient(conn),\n\t}, nil\n}\n\nfunc (c *UserClient) GetUser(ctx context.Context, userId string) (*pb.User, error) {\n\t\u002F\u002F Add metadata for tracing\n\tctx = metadata.AppendToOutgoingContext(ctx, \"x-request-id\", \"req-123\")\n\n\tctx, cancel := context.WithTimeout(ctx, 5*time.Second)\n\tdefer cancel()\n\n\treturn c.client.GetUser(ctx, &pb.GetUserRequest{\n\t\tUserId: userId,\n\t})\n}\n\nfunc (c *UserClient) ListActiveUsers(ctx context.Context) ([]*pb.User, error) {\n\tctx, cancel := context.WithTimeout(ctx, 30*time.Second)\n\tdefer cancel()\n\n\tstream, err := c.client.ListUsers(ctx, &pb.ListUsersRequest{\n\t\tPageSize:  100,\n\t\tStatusFilter: pb.UserStatus_USER_STATUS_ACTIVE,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar users []*pb.User\n\tfor {\n\t\tuser, err := stream.Recv()\n\t\tif err != nil {\n\t\t\tif err.Error() == \"EOF\" {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tusers = append(users, user)\n\t}\n\n\treturn users, nil\n}\n\nfunc (c *UserClient) Close() error {\n\treturn c.conn.Close()\n}\n\n\u002F\u002F Interceptors\nfunc loggingInterceptor(\n\tctx context.Context,\n\tmethod string,\n\treq, reply interface{},\n\tcc *grpc.ClientConn,\n\tinvoker grpc.UnaryInvoker,\n\topts ...grpc.CallOption,\n) error {\n\tstart := time.Now()\n\t\n\terr := invoker(ctx, method, req, reply, cc, opts...)\n\t\n\tlog.Printf(\"gRPC call: %s, duration: %v, error: %v\",\n\t\tmethod, time.Since(start), err)\n\t\n\treturn err\n}\n\nfunc streamLoggingInterceptor(\n\tctx context.Context,\n\tdesc *grpc.StreamDesc,\n\tcc *grpc.ClientConn,\n\tmethod string,\n\tstream grpc.ClientStream,\n\topts ...grpc.CallOption,\n) error {\n\tstart := time.Now()\n\t\n\terr := stream.RecvMsg(nil)\n\t\n\tlog.Printf(\"gRPC stream: %s, duration: %v, error: %v\",\n\t\tmethod, time.Since(start), err)\n\t\n\treturn err\n}\n```\n\n## Error Handling\n```go\npackage status\n\nimport (\n\t\"google.golang.org\u002Fgrpc\u002Fcodes\"\n\t\"google.golang.org\u002Fgrpc\u002Fstatus\"\n)\n\n\u002F\u002F Custom error codes\nconst (\n\tErrCodeUserNotFound = \"USER_NOT_FOUND\"\n\tErrCodeInvalidInput = \"INVALID_INPUT\"\n\tErrCodeUnauthorized = \"UNAUTHORIZED\"\n)\n\nfunc UserNotFound(id string) error {\n\treturn status.Errorf(codes.NotFound, \"user not found: %s\", id)\n}\n\nfunc InvalidInput(field, reason string) error {\n\treturn status.Errorf(codes.InvalidArgument, \"invalid %s: %s\", field, reason)\n}\n\nfunc Unauthorized(reason string) error {\n\treturn status.Errorf(codes.Unauthenticated, \"unauthorized: %s\", reason)\n}\n```\n\n## gRPC Best Practices\n```\n1. Use Protocol Buffers for schema\n   - Define contracts explicitly\n   - Enable backwards compatibility\n\n2. Handle errors properly\n   - Use gRPC status codes\n   - Include error details\n\n3. Implement interceptors\n   - Logging, auth, metrics\n\n4. Use streaming appropriately\n   - Server streaming for lists\n   - Bidirectional for real-time\n\n5. Set timeouts\n   - Always use context with timeout\n\n6. Enable reflection\n   - For debugging and tools\n\n7. Version your APIs\n   - Include version in package name\n   - Support multiple versions\n\n8. Use proper authentication\n   - Token-based or mTLS\n\n9. Monitor and trace\n   - Add interceptors for metrics\n   - Use OpenTelemetry\n\n10. Test thoroughly\n    - Unit tests with mock stores\n    - Integration tests\n```\n",{"name":5,"license":15,"metadata":31,"description":7,"compatibility":23},{"audience":32,"category":25},"developers","main","2ea764e153842704d24a2e9aa4170441a7f03081",".opencode\u002Fskills\u002Fgrpc","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito","https:\u002F\u002Fgithub.com\u002FNeuralBlitz","nuralnexus.org","Theoretical and Futuristic AI Nerd 🤓 ","2026-11-12 03:13:05",{"source":8,"skillName":5,"commands":42,"prompt":52,"zipAvailable":53},[43,46,49],{"tool":44,"command":45},"npx","npx skills add NeuralBlitz\u002FMito --skill grpc",{"tool":47,"command":48},"bunx","bunx skills add NeuralBlitz\u002FMito --skill grpc",{"tool":50,"command":51},"pnpm","pnpm dlx skills add NeuralBlitz\u002FMito --skill grpc","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fgrpc\u002FSKILL.md",true,[],[56,72,83,96,104,128],{"skillNo":57,"name":58,"nameZh":6,"description":59,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":60,"categories":61,"keywords":62,"publishedAt":26},"01M6HAZSAQK1S27CEZYAYJTQDX","wireless-communications","Wireless systems, mobile networks, and 5G\u002F6G","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fwireless-communications\u002FSKILL.md",[],[63,64,65,66,67,68,69,70,23,71],"communications","wireless communications","wireless","systems","engineering","networks","5G","students","mobile",{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":78,"publishedAt":26},"01M6HAZFX6E8NK3WZWDX5YCKYY","websockets","WebSocket implementation and best practices","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fwebassembly\u002Fwebsockets\u002FSKILL.md",[],[74,79,80,24,23,81,82,20],"websocket implementation","time","real-time","websocket",{"skillNo":84,"name":85,"nameZh":6,"description":86,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":87,"categories":88,"keywords":89,"publishedAt":26},"01M6HAZ6DAXBQ7QHXXM1EM7715","vulnerability-auditing","Vulnerability assessment and auditing","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fvulnerability-auditing\u002FSKILL.md",[],[90,91,92,93,23,94,95],"vulnerability","vulnerability auditing","security","vulnerability assessment","cybersecurity","assessment",{"skillNo":97,"name":98,"nameZh":6,"description":99,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":100,"categories":101,"keywords":102,"publishedAt":26},"01M6HAZ3FKF3CS9Z3J96RVE2ZE","vulnerability-assessment","Finding and assessing security vulnerabilities","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fvue\u002Fvulnerability-assessment\u002FSKILL.md",[],[93,90,95,92,103,23],"vulnerabilities",{"skillNo":105,"name":106,"nameZh":6,"description":107,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":120,"publishedAt":26},"01M6HAYSHM6HKRKEHFP0SGZQX7","vlsi-design","Very-Large-Scale Integration circuit design and semiconductor engineering","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fvlsi-design\u002FSKILL.md",[110,115],{"categoryNo":111,"categoryName":112,"taxonomyType":113,"taxonomyTypeDesc":114},"01JBSEEDCAT000000000000015","视觉设计","SCENARIO","使用场景",{"categoryNo":116,"categoryName":117,"taxonomyType":118,"taxonomyTypeDesc":119},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[121,122,19,123,124,67,125,23,126,70,127],"vlsi design","VLSI","hardware","integration","computer","scale","circuit",{"skillNo":129,"name":130,"nameZh":6,"description":131,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":132,"categories":133,"keywords":134,"publishedAt":26},"01M6HAYPQ30FFE2JXD7WQJ8R6C","unsupervised","Unsupervised learning concepts","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fvisualization\u002Funsupervised\u002FSKILL.md",[],[130,135,23,136,137,138,139,140],"learning","intelligence","unsupervised learning","machine","concepts","machine-learning"]