面试题答案
一键面试- 定义统一接口: 定义一个接口,该接口包含不同服务间交互需要的方法。例如,假设服务间需要进行数据的发送和接收,可定义如下接口:
type ServiceCommunicator interface {
Send(data []byte, target string) error
Receive() ([]byte, error)
}
- 针对不同协议实现接口:
- HTTP实现:
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
type HTTPCommunicator struct{}
func (h *HTTPCommunicator) Send(data []byte, target string) error {
resp, err := http.Post(target, "application/octet-stream", bytes.NewBuffer(data))
if err != nil {
return err
}
defer resp.Body.Close()
_, err = ioutil.ReadAll(resp.Body)
return err
}
func (h *HTTPCommunicator) Receive() ([]byte, error) {
// 这里假设是作为HTTP服务端接收数据,简单示例
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
data, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
w.Write(data)
})
return nil, http.ListenAndServe(":8080", nil)
}
- **gRPC实现**:
首先需要定义gRPC的服务和消息结构,假设已经有了proto文件并生成了Go代码。
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
pb "path/to/your/proto"
)
type GRPCCommunicator struct{}
func (g *GRPCCommunicator) Send(data []byte, target string) error {
conn, err := grpc.Dial(target, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return err
}
defer conn.Close()
client := pb.NewYourServiceClient(conn)
req := &pb.SendRequest{Data: data}
_, err = client.SendData(context.Background(), req)
return err
}
func (g *GRPCCommunicator) Receive() ([]byte, error) {
// 实现gRPC服务端接收数据
lis, err := net.Listen("tcp", ":50051")
if err != nil {
return nil, err
}
s := grpc.NewServer()
pb.RegisterYourServiceServer(s, &server{})
fmt.Println("gRPC server listening on :50051")
return nil, s.Serve(lis)
}
type server struct {
pb.UnimplementedYourServiceServer
}
func (s *server) SendData(ctx context.Context, req *pb.SendRequest) (*pb.SendResponse, error) {
return &pb.SendResponse{Status: "OK"}, nil
}
- 使用接口进行服务间交互:
在需要进行服务交互的地方,使用
ServiceCommunicator
接口,而不关心具体的协议实现。
func interact(communicator ServiceCommunicator) {
data := []byte("Hello, other service!")
err := communicator.Send(data, "target-service-address")
if err != nil {
fmt.Println("Send error:", err)
}
receivedData, err := communicator.Receive()
if err != nil {
fmt.Println("Receive error:", err)
}
fmt.Println("Received data:", string(receivedData))
}
然后可以根据实际需求选择不同的协议实现:
func main() {
httpCommunicator := &HTTPCommunicator{}
interact(httpCommunicator)
grpcCommunicator := &GRPCCommunicator{}
interact(grpcCommunicator)
}
通过上述步骤,利用Go接口实现了不同通信协议之间的适配,确保服务间能顺利交互。具体实现中,HTTP和gRPC部分的代码仅为示例,实际应用中需要根据具体的业务需求进行完善。