grpc
- grpc
- grpc-go
gRPC seamlessly integrates Protobuf.
protobuf
- For those accustomed to JSON and XML data storage formats, I believe most of you haven't heard of Protocol Buffer.
- Protocol Buffer is actually a lightweight & efficient structured data storage format developed by Google, and its performance is truly much stronger than JSON and XML!
- Protobuf has gone through protobuf2 and protobuf3, with pb3 being significantly simplified compared to pb2. The current mainstream version is pb3.
Downloading protoc
Download protoc andgo get github.com/golang/protobuf/protoc-gen-go
syntax = "proto3";
option go_package = "."; //这名不写现在编译不了
message HelloRequest {
string name = 1; //1 是编号不是值
}
protoc --proto_path=. \
--go_out=. \
--go-grpc_out=. \
./helloworld.proto
This will generate ahelloworld.pb.gofile in the directory.
Comparison of compression ratios
package main
import (
"RpcLearn/protobuf"
"encoding/json"
"fmt"
"github.com/golang/protobuf/proto"
)
// TIP <p>To run your code, right-click the code and select <b>Run</b>.</p> <p>Alternatively, click
// the <icon src="AllIcons.Actions.Execute"/> icon in the gutter and select the <b>Run</b> menu item from here.</p>
type Hello struct {
Name string `json:"name"`
}
func main() {
//TIP <p>Press <shortcut actionId="ShowIntentionActions"/> when your caret is at the underlined text
// to see how GoLand suggests fixing the warning.</p><p>Alternatively, if available, click the lightbulb to view possible fixes.</p>
//s := "gopher"
//fmt.Printf("Hello and welcome, %s!\n", s)
//
//for i := 1; i <= 5; i++ {
// //TIP <p>To start your debugging session, right-click your code in the editor and select the Debug option.</p> <p>We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
// // for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.</p>
// fmt.Println("i =", 100/i)
//}
jsonStruct := Hello{
Name: "gopher",
}
jsonReq, _ := json.Marshal(jsonStruct)
fmt.Println(string(jsonReq))
fmt.Println(len(jsonReq))
req := __.HelloRequest{
Name: "gopher",
}
rsp, _ := proto.Marshal(&req)
fmt.Println(rsp)
fmt.Println(len(rsp))
}
Approximately a twofold difference.
Explanation of Changes in Using Protobuf with Go Language
| Tutorial Content | Current Reality |
|---|---|
Previously, there was only one .pb.go file. |
Now, two files are generated: one .pb.go (data structure) and one _grpc.pb.go (gRPC interface). |
| Plugins not separated | Plugins have been split into protoc-gen-go and protoc-gen-go-grpc, requiring separate installation and invocation. |
📌 Current Behavior Explanation
Starting from Go's Protobuf plugin v1.20+, gRPC support has been split into a separate plugin, protoc-gen-go-grpc, used to generate service interface-related code. This approach is more modular and has clearer responsibilities.
Therefore, execute the following command:
protoc --proto_path=. \
--go_out=. \
--go-grpc_out=. \
./your_file.proto
This will generate:
- your_file.pb.go: Contains message structures (e.g., Request, Response)
- your_file_grpc.pb.go: Contains service interface definitions (e.g., YourServiceServer)
It is recommended to retain and synchronize these two files.
Briefly Outline the gRPC Startup Process
- Create stub files and method definitions, then compile.
// proto/helloworld.proto
syntax = "proto3";
option go_package = ".;proto";
service Greeter{
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
- The server-side implements the call to the defined method, noting the server implementation (duck typing).
package main
import (
"RpcLearn/grpc_test/proto"
"context"
"google.golang.org/grpc"
"log"
"net"
)
type Server struct {
proto.UnimplementedGreeterServer // 👈 重点:嵌入这个类型
}
func (s *Server) SayHello(ctx context.Context, req *proto.HelloRequest) (*proto.HelloReply, error) {
reply := &proto.HelloReply{
Message: "Hello " + req.Name,
}
return reply, nil
}
func main() {
g := grpc.NewServer() // 创建一个新的gRPC服务器
proto.RegisterGreeterServer(g, &Server{}) // 注册服务
listener, err := net.Listen("tcp", ":9090")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
err = g.Serve(listener)
if err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
- Client-side call implementation.
package main
import (
"RpcLearn/grpc_test/proto"
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func main() {
// Create a new gRPC server
//conn, err := grpc.Dial("localhost:9090", grpc.WithInsecure())
// 使用安全连接
//creds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})
conn, err := grpc.NewClient("localhost:9090",
//grpc.WithInsecure()
grpc.WithTransportCredentials(insecure.NewCredentials()), // ✅ 新方式
)
if err != nil {
panic(err)
}
defer conn.Close()
c := proto.NewGreeterClient(conn)
r, err := c.SayHello(context.Background(), &proto.HelloRequest{Name: "world"})
if err != nil {
panic(err)
}
fmt.Println(r.Message)
}
gRPC Stream Method (Streaming Mode)
- Simple mode (simple RPC)
- Server-side data stream
- Client-side data stream
- Bidirectional
Focused Learning on gRPC
| Protobuf Type | Go Type |
|---|---|
| double | float64 |
| float | float32 |
| int32 | int32 |
| int64 | int64 |
| uint32 | uint32 |
| uint64 | uint64 |
| sint32 | int32 |
| sint64 | int64 |
| fixed32 | uint32 |
| fixed64 | uint64 |
Default values
Default Value Explanation
In Protobuf, different field types have the following default values:
- String type (string): The default value is an empty string.
- Byte type (bytes): The default value is an empty byte sequence.
- Boolean type (bool): The default value is
false. - Numeric types (number types): The default value is
0. - Enum type: The default value is the first defined enum value, and it must be
0. - Message type (message): The default value is unset (i.e.,
null).
Notes
- For scalar message fields: Once a message is parsed, it's impossible to distinguish whether a field was set to its default value (
主题测试文章,只做测试使用。发布者:Walker,转转请注明出处:https://walker-learn.xyz/archives/4772