ProtoBuf 的 Golang 解析
Golang Parsing of ProtoBuf
我是 Golang 的新手,我正在尝试使用 Micro 框架和 Protobuf 框架在 Golang 中编写一个家庭自动化框架。
我目前很难尝试实现一个简单的注册表类型服务。
我遇到的问题的一个例子是我有以下问题,我希望能够获得设备列表,前提是客户端向 http://localhost:8080/view/devices
发出 GET 请求
我有以下 protobuf 定义:
syntax = "proto3";
service DRegistry {
rpc View(ViewRequest) returns (DeviceRegistry) {}
}
message DeviceRegistry {
repeated Device devices = 1;
}
message ViewRequest {
string Alias = 1;
}
message Device {
string Alias = 1;
string HWAddress = 2;
string WakeUpMethod = 3;
repeated string BoundServices = 4;
}
然后在我的服务定义中有以下内容:
package main
import (
"log"
micro "github.com/micro/go-micro"
proto "github.com/srizzling/gotham/proto/device"
"golang.org/x/net/context"
)
// DRegistry stands for Device Registry and is how devices register to Gotham.
type DRegistry struct{}
var devices map[string]proto.Device
func (g *DRegistry) View(ctx context.Context, req *proto.ViewRequest, rsp *proto.DeviceRegistry) error {
filter := req.Alias
devices, err := filterDevices(filter)
rsp.Devices = devices
}
func filterDevices(filter string) (*[]proto.Device, error) {
// Currently only supports listing a single service for now
// TODO: expand filter to be more consise
filteredDevices := make([]proto.Device, 0, len(devices))
for _, e := range devices {
for _, f := range e.BoundServices {
if f == filter {
filteredDevices = append(filteredDevices, e)
}
}
}
return &filteredDevices, nil
}
func main() {
service := micro.NewService(
micro.Name("DRegistry"),
)
proto.RegisterDRegistryHandler(service.Server(), new(DRegistry))
if err := service.Run(); err != nil {
log.Fatal(err)
}
}
我遇到的问题是我的 IDE(Visual Studio 代码)符合我 cannot use devices (type *[]device.Device) as type []*device.Device in assignment
的要求,这令人困惑。
TLDR:如何将 proto.Devices 的集合分配给 proto.DeviceRegistry?
func filterDevices(filter string) ([]*proto.Device, error) {
// Currently only supports listing a single service for now
// TODO: expand filter to be more consise
filteredDevices := make([]*proto.Device, 0, len(devices))
for _, e := range devices {
for _, f := range e.BoundServices {
if f == filter {
filteredDevices = append(filteredDevices, &e)
}
}
}
return filteredDevices, nil
}
指针切片 ([]*) 和指向切片的指针 (*[]) 之间存在 的区别。您正在 returning 一个指向切片的指针,而您想要的是一个指针切片。我们可以通过以下方式解决这个问题:
- 正在将您的
filterDevices
签名更新为 return 一片指针
- 正在更新您的
make
调用以生成指针片段
- 在追加调用中获取
e
的地址(我们需要一部分指向设备的指针)
- 不是 returning slice的地址
我是 Golang 的新手,我正在尝试使用 Micro 框架和 Protobuf 框架在 Golang 中编写一个家庭自动化框架。
我目前很难尝试实现一个简单的注册表类型服务。
我遇到的问题的一个例子是我有以下问题,我希望能够获得设备列表,前提是客户端向 http://localhost:8080/view/devices
我有以下 protobuf 定义:
syntax = "proto3";
service DRegistry {
rpc View(ViewRequest) returns (DeviceRegistry) {}
}
message DeviceRegistry {
repeated Device devices = 1;
}
message ViewRequest {
string Alias = 1;
}
message Device {
string Alias = 1;
string HWAddress = 2;
string WakeUpMethod = 3;
repeated string BoundServices = 4;
}
然后在我的服务定义中有以下内容:
package main
import (
"log"
micro "github.com/micro/go-micro"
proto "github.com/srizzling/gotham/proto/device"
"golang.org/x/net/context"
)
// DRegistry stands for Device Registry and is how devices register to Gotham.
type DRegistry struct{}
var devices map[string]proto.Device
func (g *DRegistry) View(ctx context.Context, req *proto.ViewRequest, rsp *proto.DeviceRegistry) error {
filter := req.Alias
devices, err := filterDevices(filter)
rsp.Devices = devices
}
func filterDevices(filter string) (*[]proto.Device, error) {
// Currently only supports listing a single service for now
// TODO: expand filter to be more consise
filteredDevices := make([]proto.Device, 0, len(devices))
for _, e := range devices {
for _, f := range e.BoundServices {
if f == filter {
filteredDevices = append(filteredDevices, e)
}
}
}
return &filteredDevices, nil
}
func main() {
service := micro.NewService(
micro.Name("DRegistry"),
)
proto.RegisterDRegistryHandler(service.Server(), new(DRegistry))
if err := service.Run(); err != nil {
log.Fatal(err)
}
}
我遇到的问题是我的 IDE(Visual Studio 代码)符合我 cannot use devices (type *[]device.Device) as type []*device.Device in assignment
的要求,这令人困惑。
TLDR:如何将 proto.Devices 的集合分配给 proto.DeviceRegistry?
func filterDevices(filter string) ([]*proto.Device, error) {
// Currently only supports listing a single service for now
// TODO: expand filter to be more consise
filteredDevices := make([]*proto.Device, 0, len(devices))
for _, e := range devices {
for _, f := range e.BoundServices {
if f == filter {
filteredDevices = append(filteredDevices, &e)
}
}
}
return filteredDevices, nil
}
指针切片 ([]*) 和指向切片的指针 (*[]) 之间存在 的区别。您正在 returning 一个指向切片的指针,而您想要的是一个指针切片。我们可以通过以下方式解决这个问题:
- 正在将您的
filterDevices
签名更新为 return 一片指针 - 正在更新您的
make
调用以生成指针片段 - 在追加调用中获取
e
的地址(我们需要一部分指向设备的指针) - 不是 returning slice的地址