基于 SOC 职业分类
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/pluginagentmarketplace/custom-plugin-go --skill go-grpc命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | go-grpc |
| description | Build gRPC services with Go - protobuf, streaming, interceptors |
| sasmp_version | 1.3.0 |
| bonded_agent | 07-go-microservices |
| bond_type | PRIMARY_BOND |
Build high-performance gRPC services with Go.
Complete guide for gRPC development including protobuf design, streaming, interceptors, and error handling.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| streaming | string | no | "unary" | Type: "unary", "server", "client", "bidi" |
| auth | string | no | "none" | Auth: "none", "jwt", "mtls" |
syntax = "proto3";
package api.v1;
option go_package = "github.com/example/api/v1;apiv1";
service UserService {
rpc GetUser(GetUserRequest) returns (GetUserResponse);
rpc ListUsers(ListUsersRequest) returns (stream User);
rpc CreateUser(CreateUserRequest) returns (CreateUserResponse);
}
message User {
int64 id = 1;
string name = 2;
string email = 3;
google.protobuf.Timestamp created_at = 4;
}
type userServer struct {
apiv1.UnimplementedUserServiceServer
store UserStore
}
func (s *userServer) GetUser(ctx context.Context, req *apiv1.GetUserRequest) (*apiv1.GetUserResponse, error) {
user, err := s.store.FindByID(ctx, req.Id)
if err != nil {
if errors.Is(err, ErrNotFound) {
return nil, status.Error(codes.NotFound, "user not found")
}
return nil, status.Error(codes.Internal, "internal error")
}
return &apiv1.GetUserResponse{
User: toProtoUser(user),
}, nil
}
func (s *userServer) ListUsers(req *apiv1.ListUsersRequest, stream apiv1.UserService_ListUsersServer) error {
users, err := s.store.List(stream.Context(), req.PageSize)
if err != nil {
return status.Error(codes.Internal, "failed to list users")
}
for _, user := range users {
if err := stream.Send(toProtoUser(user)); err != nil {
return err
}
}
return nil
}
func LoggingInterceptor(logger *slog.Logger) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
start := time.Now()
resp, err := handler(ctx, req)
logger.Info("grpc call",
"method", info.FullMethod,
"duration", time.Since(start),
"error", err,
)
return resp, err
}
}
func RecoveryInterceptor() grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
defer func() {
if r := recover(); r != nil {
err = status.Errorf(codes.Internal, "panic: %v", r)
}
}()
return handler(ctx, req)
}
}
func NewClient(addr string) (apiv1.UserServiceClient, error) {
conn, err := grpc.Dial(addr,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithUnaryInterceptor(
grpc_retry.UnaryClientInterceptor(
grpc_retry.WithMax(3),
grpc_retry.WithBackoff(grpc_retry.BackoffExponential(100*time.Millisecond)),
grpc_retry.WithCodes(codes.Unavailable, codes.ResourceExhausted),
),
),
)
if err != nil {
return nil, err
}
return apiv1.NewUserServiceClient(conn), nil
}
| Code | Use Case |
|---|---|
| OK | Success |
| INVALID_ARGUMENT | Bad input |
| NOT_FOUND | Resource missing |
| ALREADY_EXISTS | Duplicate |
| DEADLINE_EXCEEDED | Timeout |
| UNAVAILABLE | Service down |
| INTERNAL | Server bug |
grpcurl -plaintext localhost:50051 list
grpcurl -plaintext -d '{"id": 1}' localhost:50051 api.v1.UserService/GetUser
Skill("go-grpc")