Introduction to gRPC and Protobuf with Go: Definitions, Syntax, and Example Implementation
This article provides a comprehensive beginner-friendly guide to gRPC, covering its definition, the protobuf syntax for defining messages and services, field constraints, supported data types, usage of the protoc tool, and complete Go examples for both server and client implementations.
Introduction
gRPC is a high‑performance, open‑source RPC framework developed by Google, built on the HTTP/2 protocol and using Protocol Buffers (protobuf) for serialization. It supports many programming languages and is widely used when strict interface contracts or large data transfers are required.
What is protobuf?
ProtoBuf is a data‑description format stored in .proto files. Using the protoc compiler, you can generate language‑specific access classes. The workflow consists of defining data entities and then generating the corresponding access classes.
Protobuf syntax for defining data entities
syntax = "proto3";
package studentpb;
service Student {
rpc add (StudentReqs) returns (StudentReply) {} // 新增学生接口
}
message StudentReqs {
repeated StudentReq s = 1;
}
message StudentReq {
string name = 1;
int32 age = 2;
}
message StudentReply {
int32 errno = 1;
string errmsg = 2;
}The key keywords are:
syntax : specifies the proto version (e.g., proto3 ).
package : defines a namespace to avoid naming conflicts.
message : defines the structure of request or response payloads; multiple messages can be defined in one file.
service : declares RPC methods with input and output message types.
Field constraint rules
repeated : marks a field as an array (list) type.
Proto3 does not support the required and optional keywords that existed in proto2.
Supported field types
Protobuf supports basic scalar types, enum types, map types, repeated (array) types, and nested message types.
Using the protoc tool
To generate Go code from .proto files, run:
protoc --go_out=plugins=grpc:. *.protoThis command creates Go structs and gRPC stubs for the defined services.
Go server implementation
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"log"
"net"
"test/studentpb"
)
type Student struct{}
// Add implements the Add RPC
func (r *Student) Add(ctx context.Context, in *studentpb.StudentReqs) (*studentpb.StudentReply, error) {
return &studentpb.StudentReply{Errno: 0, Errmsg: "ok"}, nil
}
func main(){
rpcAddr := "127.0.0.1:8601"
server, err := net.Listen("tcp", rpcAddr)
if err != nil {
fmt.Println("failed to listen", rpcAddr)
panic(err)
}
var RpcServer = grpc.NewServer()
studentpb.RegisterStudentServer(RpcServer, &Student{})
go func(){
if err = RpcServer.Serve(server); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}()
select{}
}Go client implementation
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"test/studentpb"
"time"
)
func main(){
addr := "127.0.0.1:8601"
timeout := 10
client, err := grpc.Dial(addr, grpc.WithInsecure())
if err != nil { panic("连接失败") }
defer client.Close()
rpcClient := studentpb.NewStudentClient(client)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
defer cancel()
req := &studentpb.StudentReqs{}
req.S = append(req.S, &studentpb.StudentReq{Name:"张三", Age:12})
res, err := rpcClient.Add(ctx, req)
if err != nil { fmt.Println("请求错误", err) } else { fmt.Println(res.GetErrno(), res.GetErrmsg()) }
}The article walks readers through the entire process—from understanding gRPC and protobuf basics, writing .proto definitions, generating Go code with protoc , to implementing a functional server and client that communicate via gRPC.
360 Tech Engineering
Official tech channel of 360, building the most professional technology aggregation platform for the brand.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.