@
目錄
- 寫在前面
- 客戶端 unary interceptor
- 伺服器 nuary interceptor
- 客戶端 stream interceptor
- 伺服器 stream interceptor
- 伺服器 多 unay interceptor
- 具體例子
- 伺服器 unary interceptor
- 多攔截器
- 參考資料
基礎/標準庫/第三方庫
golang 導航
程式設計規範
演算法|面試
專案
寫在前面
- 相關博文
- 個人部落格首頁
- 免責宣告:僅供學習交流使用!開源框架可能存在的風險和相關後果將完全由使用者自行承擔,本人不承擔任何法律責任。
客戶端 unary interceptor
import (
"context"
"fmt"
"google.golang.org/grpc"
pb "path/to/your/protobuf/package"
)
// 客戶端一元攔截器函式
func clientUnaryInterceptor(
ctx context.Context,
method string,
req, reply interface{},
cc *grpc.ClientConn,
invoker grpc.UnaryInvoker,
opts ...grpc.CallOption,
) error {
// 在請求之前處理
fmt.Println("Before RPC call:", method)
// 呼叫實際的RPC方法
err := invoker(ctx, method, req, reply, cc, opts...)
// 在響應之後處理
fmt.Println("After RPC call:", method)
return err
}
func main() {
// 建立一個帶有攔截器的連線
conn, err := grpc.Dial(
"localhost:50051",
grpc.WithInsecure(),
grpc.WithUnaryInterceptor(clientUnaryInterceptor),
)
if err != nil {
fmt.Println("Failed to connect:", err)
return
}
defer conn.Close()
// 建立客戶端存根
client := pb.NewYourServiceClient(conn)
// 呼叫服務方法
resp, err := client.YourMethod(context.Background(), &pb.YourRequest{})
if err != nil {
fmt.Println("Error calling service:", err)
return
}
fmt.Println("Response from service:", resp)
}
伺服器 nuary interceptor
import (
"context"
"fmt"
"google.golang.org/grpc"
"net"
pb "path/to/your/protobuf/package"
)
// 伺服器端一元攔截器函式
func serverUnaryInterceptor(
ctx context.Context,
req interface{},
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler,
) (interface{}, error) {
// 在請求處理之前處理
fmt.Println("Before handling RPC call:", info.FullMethod)
// 呼叫實際的服務方法
resp, err := handler(ctx, req)
// 在響應之後處理
fmt.Println("After handling RPC call:", info.FullMethod)
return resp, err
}
type server struct {
pb.UnimplementedYourServiceServer
}
func (s *server) YourMethod(ctx context.Context, req *pb.YourRequest) (*pb.YourResponse, error) {
// 服務邏輯
return &pb.YourResponse{}, nil
}
func main() {
// 建立一個gRPC伺服器並新增一元攔截器
grpcServer := grpc.NewServer(grpc.UnaryInterceptor(serverUnaryInterceptor))
pb.RegisterYourServiceServer(grpcServer, &server{})
// 啟動伺服器
lis, err := net.Listen("tcp", ":50051")
if err != nil {
fmt.Println("Failed to listen:", err)
return
}
if err := grpcServer.Serve(lis); err != nil {
fmt.Println("Failed to serve:", err)
return
}
}
客戶端 stream interceptor
import (
"context"
"fmt"
"google.golang.org/grpc"
pb "path/to/your/protobuf/package"
)
// 客戶端流式攔截器函式
func clientStreamInterceptor(
ctx context.Context,
desc *grpc.StreamDesc,
cc *grpc.ClientConn,
method string,
streamer grpc.Streamer,
opts ...grpc.CallOption,
) (grpc.ClientStream, error) {
// 在請求之前處理
fmt.Println("Before streaming RPC call:", method)
// 呼叫實際的流式RPC方法
clientStream, err := streamer(ctx, desc, cc, method, opts...)
// 在響應之後處理
fmt.Println("After streaming RPC call:", method)
return clientStream, err
}
func main() {
// 建立一個帶有攔截器的連線
conn, err := grpc.Dial(
"localhost:50051",
grpc.WithInsecure(),
grpc.WithStreamInterceptor(clientStreamInterceptor),
)
if err != nil {
fmt.Println("Failed to connect:", err)
return
}
defer conn.Close()
// 建立客戶端存根
client := pb.NewYourServiceClient(conn)
// 呼叫服務方法
stream, err := client.YourStreamingMethod(context.Background())
if err != nil {
fmt.Println("Error calling service:", err)
return
}
// 處理流資料
for {
resp, err := stream.Recv()
if err != nil {
if err == io.EOF {
break
}
fmt.Println("Error receiving stream:", err)
return
}
fmt.Println("Received message from stream:", resp)
}
}
伺服器 stream interceptor
import (
"context"
"fmt"
"google.golang.org/grpc"
"net"
pb "path/to/your/protobuf/package"
)
// 伺服器端流式攔截器函式
func serverStreamInterceptor(
srv interface{},
ss grpc.ServerStream,
info *grpc.StreamServerInfo,
handler grpc.StreamHandler,
) error {
// 在請求處理之前處理
fmt.Println("Before handling streaming RPC call:", info.FullMethod)
// 呼叫實際的流式RPC方法
err := handler(srv, ss)
// 在響應之後處理
fmt.Println("After handling streaming RPC call:", info.FullMethod)
return err
}
type server struct {
pb.UnimplementedYourServiceServer
}
func (s *server) YourStreamingMethod(stream pb.YourService_YourStreamingMethodServer) error {
// 服務邏輯
return nil
}
func main() {
// 建立一個gRPC伺服器並新增流式攔截器
grpcServer := grpc.NewServer(grpc.StreamInterceptor(serverStreamInterceptor))
pb.RegisterYourServiceServer(grpcServer, &server{})
// 啟動伺服器
lis, err := net.Listen("tcp", ":50051")
if err != nil {
fmt.Println("Failed to listen:", err)
return
}
if err := grpcServer.Serve(lis); err != nil {
fmt.Println("Failed to serve:", err)
return
}
}
伺服器 多 unay interceptor
import (
"context"
"fmt"
"google.golang.org/grpc"
"net"
pb "path/to/your/protobuf/package"
)
// 第一個伺服器端一元攔截器
func firstServerUnaryInterceptor(
ctx context.Context,
req interface{},
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler,
) (interface{}, error) {
fmt.Println("First unary interceptor - Before handling RPC call:", info.FullMethod)
resp, err := handler(ctx, req)
fmt.Println("First unary interceptor - After handling RPC call:", info.FullMethod)
return resp, err
}
// 第二個伺服器端一元攔截器
func secondServerUnaryInterceptor(
ctx context.Context,
req interface{},
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler,
) (interface{}, error) {
fmt.Println("Second unary interceptor - Before handling RPC call:", info.FullMethod)
resp, err := handler(ctx, req)
fmt.Println("Second unary interceptor - After handling RPC call:", info.FullMethod)
return resp, err
}
type server struct {
pb.UnimplementedYourServiceServer
}
func (s *server) YourMethod(ctx context.Context, req *pb.YourRequest) (*pb.YourResponse, error) {
return &pb.YourResponse{}, nil
}
func main() {
// 建立一個帶有多個攔截器的gRPC伺服器
grpcServer := grpc.NewServer(
grpc.ChainUnaryInterceptor(firstServerUnaryInterceptor, secondServerUnaryInterceptor),
)
pb.RegisterYourServiceServer(grpcServer, &server{})
// 啟動伺服器
lis, err := net.Listen("tcp", ":50051")
if err != nil {
fmt.Println("Failed to listen:", err)
return
}
if err := grpcServer.Serve(lis); err != nil {
fmt.Println("Failed to serve:", err)
return
}
}
具體例子
伺服器 unary interceptor
"context"
assetfs "github.com/elazarl/go-bindata-assetfs"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/reflection"
"log"
"net/http"
"path"
"strings"
)
func handleRpc() *grpc.Server {
//a := api.Api{Ctx: context.TODO(), Url: "http://localhost", Ak: "string", Sk: "string"}
//list, err := a.TagList()
//fmt.Printf("%#v,%s", list, err)
tag := server.NewTag("http://localhost:8080", "string", "string")
//res, err := tag.TagList()
//if err != nil {
// return
//}
//fmt.Printf("%s,%s", res.String(), err)
interceptors := []grpc.ServerOption{grpc.UnaryInterceptor(HelloInterceptor)}
svc := grpc.NewServer(interceptors...)
proto.RegisterTagSvcServer(svc, tag)
reflection.Register(svc)
return svc
}
func handleGrpcGateway(port string) *runtime.ServeMux {
endpoint := "0.0.0.0:" + port
g := runtime.NewServeMux()
dopts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
_ = proto.RegisterTagSvcHandlerFromEndpoint(context.Background(), g, endpoint, dopts)
return g
}
func HelloInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
log.Println("你好")
resp, err := handler(ctx, req)
log.Println("再見")
return resp, err
}
多攔截器
func handleRpc() *grpc.Server {
//a := api.Api{Ctx: context.TODO(), Url: "http://localhost", Ak: "string", Sk: "string"}
//list, err := a.TagList()
//fmt.Printf("%#v,%s", list, err)
tag := server.NewTag("http://localhost:8080", "string", "string")
//res, err := tag.TagList()
//if err != nil {
// return
//}
//fmt.Printf("%s,%s", res.String(), err)
interceptors := grpc.ChainUnaryInterceptor(HelloInterceptor, WorldInterceptor)
svc := grpc.NewServer(interceptors)
proto.RegisterTagSvcServer(svc, tag)
reflection.Register(svc)
return svc
}
func handleGrpcGateway(port string) *runtime.ServeMux {
endpoint := "0.0.0.0:" + port
g := runtime.NewServeMux()
dopts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
_ = proto.RegisterTagSvcHandlerFromEndpoint(context.Background(), g, endpoint, dopts)
return g
}
func HelloInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
log.Println("你好")
resp, err := handler(ctx, req)
log.Println("再見")
return resp, err
}
func WorldInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
log.Println("你好")
resp, err := handler(ctx, req)
log.Println("再見")
return resp, err
}
參考資料
基礎/標準庫/第三方庫
- 地鼠文件:比較多資料
- topgoer
- go awesome
- golang 文件學習
- golang 標準庫
- go 檔案常用操作
golang 導航
- golang 收集
- go-guide
- golang 導航
- go-concurrency-guide
- go-advice
- golang 知識路線
程式設計規範
- golang 程式設計規範
- golang 規範示例
演算法|面試
- cs 面試
- 面試網站
- Golang後端研發崗位相關面試題和簡歷
- 路人張的面試筆記
- golang 演算法
專案
- golang 專案推薦
- 7天系列
- go專案推薦
- go高效能程式設計