Golang gRPC中遇到undefined: RegisterChatServiceServer错误如何解决
Golang gRPC中遇到undefined: RegisterChatServiceServer错误如何解决 尝试使用Go构建我的第一个gRPC应用,步骤如下:
1.1. 安装所需的Go库
PS D:\grpc> go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
PS D:\grpc> go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
1.2. 将GOPATH/bin添加到PATH环境变量中,以便命令行能够识别protoc-gen-go和protoc-gen-grpc命令。
2.1. 从以下地址为Windows下载protoc二进制文件:https://github.com/protocolbuffers/protobuf/releases/
2.2. 解压protoc压缩文件,并将其bin文件夹添加到PATH环境变量中。
3.1. 编写proto文件如下:
// file: grpc/chat/chat.proto
syntax = "proto3";
package chat;
option go_package = "github.com/hajsf/grpc/chat";
message MessageRequest {
string body = 1;
}
message MessageResponse {
string body = 1;
}
service ChatService {
rpc SayHello(MessageRequest) returns (MessageResponse) {}
}
3.3. 编译proto文件以从grpc文件夹生成chat.pb.go:
PS D:\grpc> protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative chat.proto
相应地生成了两个文件:chat.pb.go和chat_grpc.pb.go。
3.4. 添加chat.go文件如下:
// file: grpc/chat/chat.go
package main
import (
"log"
chat "github.com/hajsf/grpc/chat"
"golang.org/x/net/context"
)
type Server struct {
}
func (s *Server) SayHello(ctx context.Context, in *chat.MessageRequest) (*chat.MessageResponse, error) {
log.Printf("Receive message body from client: %s", in.Body)
return &chat.MessageResponse{Body: "Hello From the Server!"}, nil
}
- 构建服务器文件如下:
// file: grpc/server/main.go
package main
import (
"fmt"
"log"
"net"
"github.com/hajsf/grpc/chat"
"google.golang.org/grpc"
)
func main() {
fmt.Println("Go gRPC Beginners Tutorial!")
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 9000))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := chat.Server{}
grpcServer := grpc.NewServer()
chat.RegisterChatServiceServer(grpcServer, &s)
if err := grpcServer.Serve(lis); err != nil {
log.Fatalf("failed to serve: %s", err)
}
}
- 构建客户端文件如下:
// file: grpc/client/main.go
package main
import (
"log"
"golang.org/x/net/context"
"google.golang.org/grpc"
"github.com/hajsf/grpc/chat"
)
func main() {
var conn *grpc.ClientConn
conn, err := grpc.Dial(":9000", grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %s", err)
}
defer conn.Close()
c := chat.NewChatServiceClient(conn) // 为什么找不到?
response, err := c.SayHello(context.Background(), &chat.MessageRequest{Body: "Hello From Client!"})
if err != nil {
log.Fatalf("Error when calling SayHello: %s", err)
}
log.Printf("Response from server: %s", response.Body)
}
- 在上述提到的三个文件夹
chat、server和client中,分别创建了GO模块,命令如下:
PS D:\grpc> go mod init github.com/hajsf/grpc/<filenale>
PS D:\grpc> go mod tidy
- 尝试运行
server,但遇到以下错误:
PS D:\grpc\server> go run github.com/hajsf/grpc/server
# github.com/hajsf/grpc/server
.\main.go:21:12: undefined: chat.Server
.\main.go:25:7: undefined: chat.RegisterChatServiceServer
- 尝试运行
client,但遇到以下错误:
PS D:\grpc\client> go run github.com/hajsf/grpc/client
# github.com/hajsf/grpc/client
.\main.go:21:12: undefined: chat.NewChatServiceClient
代码已加载到GitHub仓库:hajsf/grpc (github.com)
更多关于Golang gRPC中遇到undefined: RegisterChatServiceServer错误如何解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于Golang gRPC中遇到undefined: RegisterChatServiceServer错误如何解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这个错误是因为你的项目结构导致了包导入路径问题。你为每个目录单独创建了Go模块,但gRPC生成的代码期望在同一个模块中。
问题分析:
chat目录是一个独立的Go模块server和client目录也是独立的Go模块- 生成的
chat_grpc.pb.go文件中的RegisterChatServiceServer和NewChatServiceClient函数在chat模块中 - 但
server和client模块无法正确访问这些函数
解决方案:
方法1:使用单一模块(推荐)
删除所有子目录的go.mod文件,只在根目录创建一个模块:
# 在D:\grpc目录下
PS D:\grpc> del chat\go.mod
PS D:\grpc> del server\go.mod
PS D:\grpc> del client\go.mod
PS D:\grpc> go mod init github.com/hajsf/grpc
PS D:\grpc> go mod tidy
然后更新你的文件结构:
// server/main.go 保持不变,但确保导入路径正确
package main
import (
"fmt"
"log"
"net"
"github.com/hajsf/grpc/chat" // 现在指向正确的包
"google.golang.org/grpc"
)
func main() {
fmt.Println("Go gRPC Beginners Tutorial!")
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 9000))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := &chat.Server{} // 注意:这里应该是你实现的Server类型
grpcServer := grpc.NewServer()
chat.RegisterChatServiceServer(grpcServer, s)
if err := grpcServer.Serve(lis); err != nil {
log.Fatalf("failed to serve: %s", err)
}
}
方法2:如果你需要保持多模块结构,修改chat.go
// chat/chat.go 需要修改
package chat // 改为chat包,而不是main
import (
"log"
"golang.org/x/net/context"
)
// 确保这个结构体实现了生成的接口
type Server struct {
chat.UnimplementedChatServiceServer // 嵌入这个以向前兼容
}
func (s *Server) SayHello(ctx context.Context, in *MessageRequest) (*MessageResponse, error) {
log.Printf("Receive message body from client: %s", in.Body)
return &MessageResponse{Body: "Hello From the Server!"}, nil
}
然后在server中正确导入:
// server/main.go
package main
import (
"fmt"
"log"
"net"
"github.com/hajsf/grpc/chat"
"google.golang.org/grpc"
)
func main() {
fmt.Println("Go gRPC Beginners Tutorial!")
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 9000))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := &chat.Server{}
grpcServer := grpc.NewServer()
// 现在这个函数应该可以找到了
chat.RegisterChatServiceServer(grpcServer, s)
if err := grpcServer.Serve(lis); err != nil {
log.Fatalf("failed to serve: %s", err)
}
}
方法3:检查protoc生成的文件
确保protoc命令正确生成了所有必要的代码。检查chat_grpc.pb.go文件是否包含:
// 应该有这样的函数
func RegisterChatServiceServer(s grpc.ServiceRegistrar, srv ChatServiceServer) {
s.RegisterService(&ChatService_ServiceDesc, srv)
}
// 和这样的函数
func NewChatServiceClient(cc grpc.ClientConnInterface) ChatServiceClient {
return &chatServiceClient{cc}
}
重新生成protobuf文件:
PS D:\grpc> protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative chat/chat.proto
确保生成的.pb.go文件在正确的目录中,并且所有模块都能正确访问它们。

