运行一个简单的Grpc
前面我们成功的安装了Go+运行环境,下面我们通过运行一个简单的Grpc来了解下如何进行包的引用。
运行一个简单的Grpc完整地址
对于依赖库的引用 Go+ 已经做了很多优化让代码写起来更简单,就像前面执行打印时Go需要import "fmt"
才可以调用,Go+可以直接调用println
函数。但是除了基础外在日常开发中还是需要用到很多外部依赖库,还更便捷的进行开发工作,下面来了解下Go包管理工具go.mod。
Go.mod是Golang1.11版本新引入的官方包管理工具用于解决之前没有地方记录依赖包具体版本的问题,方便依赖包的管理。
Go.mod其实就是一个Modules,关于Modules的官方定义为:
Modules是相关Go包的集合,是源代码交换和版本控制的单元。go命令直接支持使用Modules,包括记录和解析对其他模块的依赖性。Modules替换旧的基于GOPATH的方法,来指定使用哪些源文件。
Modules和传统的GOPATH不同,不需要包含例如src,bin这样的子目录,一个源代码目录甚至是空目录都可以作为Modules,只要其中包含有go.mod文件。
设置代理执行go get 或 go install 安装依赖时可能会出现地址无法访问的情况,可以设置代理地址,在win10任务栏左下角的win标志右键,以管理员身份打开powershell
$env:GOPROXY = "https://goproxy.io"
如果还是无法访问,还需要设置下外网的代理
set http_proxy=127.0.0.1:19180
set https_proxy=127.0.0.1:19180
设置自动获取依赖
go env -w GO111MODULE=auto
初始化模块GO111MODULE有三个值:off, on和auto(默认值)。
GO111MODULE=off,go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者GOPATH模式来查找。
GO111MODULE=on,go命令行会使用modules,而一点也不会去GOPATH目录下查找。
GO111MODULE=auto,默认值,go命令行将会根据当前目录来决定是否启用module功能。这种情况下可以分为两种情形:
当前目录在GOPATH/src之外且该目录包含go.mod文件
当前文件在包含go.mod文件的目录下面。
测试项目目录结构如下图所示:
在根目录执行go mod {包名称} 命令后会生成一个go.mod文件,后面这个文件会记录项目使用的包和包版本,有点像Python中的requirements.txt文件。
go.mod 文件
module hello
go 1.17
注意:子目录里是不需要init的,所有的子目录里的依赖都会组织在根目录的go.mod文件里
执行 go run server.go 运行代码会发现 go mod 会自动查找依赖自动下载
go.mod 文件
module hello
go 1.17
require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/goplus/gop v1.0.14 // indirect
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect
google.golang.org/grpc v1.42.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
)
我们会执行的命令
# 初始化模块
go mod init 模块名称
# 我们的示例
go mod init hello
# 运行grpc服务端
go run server.go
引用项目文件
helloworld.proto
syntax = "proto3";
package hello;
option go_package = "/protos";
// 定义一个服务
service Greeter {
// 定义一个函数
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// 定义函数的输入
message HelloRequest {
string name = 1;
}
// 定义函数的输出
message HelloReply {
string message = 1;
}
在protos目录下是我们生成的grpc协议文件,了解proto 。首先我们需要编辑一个标准的proto协议文件,然后执行下面的编译命令生成go的协议文件。
protoc -I=$SRC_DIR --go_out=$DST_DIR $SRC_DIR/helloworld.proto
# 我们的示例
protoc.exe --go_out=plugins=grpc:. helloworld.proto
生成的helloworld.pb.go
文件是grpc客户端和grpc服务端都需要引用的文件,用来指定一个标准的通信规则,怎么来引用这个文件呢?我们在前面初始化了我们当前项目的模块名称是 hello
,所以我们在import中添加"hello/protos"
来引用该文件。
client.go
package main
import (
"log"
"os"
"golang.org/x/net/context"
"google.golang.org/grpc"
pb "hello/protos"
)
const (
address = "localhost:8888"
defaultName = "不太灵光的程序员"
)
func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.Message)
}
grpc 服务端示例
server.go
package main
import (
"log"
"net"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
pb "hello/protos"
)
const (
port = ":8888"
)
// GreeterServerImplementation is used to implement helloworld.GreeterServer.
type GreeterServerImplementation struct{}
// SayHello implements helloworld.GreeterServer
func (s *GreeterServerImplementation) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &GreeterServerImplementation{})
// Register reflection service on gRPC server.
reflection.Register(s)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
运行结果
# 运行grpc服务端
go run server.go
# 运行grpc客户端
go run client.go
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)