1

I'm new to Golang and I am trying to write an home automation framework in Golang, using the Micro framework and Protobuf framework.

I am currently having a hard time trying to implement a simple registry type service.

An example of the problem I am having is that I have the following, I want to be able to get a list of devices, provided a client does a GET request to http://localhost:8080/view/devices

I have the following protobuf definition:

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;
}

Then in my service defination I have the following:

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)
    }
}

The problem I am having is that my IDE (Visual Studio Code) is complianing that I cannot use devices (type *[]device.Device) as type []*device.Device in assignment which is confusing.

TLDR: How do I assign a collection of proto.Devices to the proto.DeviceRegistry?

2
  • Hi! On what line do yo get the error message? *[]device.Device -- pointer to a slice of device.Device. []*device.Device -- slice of pointers to a device.Device. This read might be useful to you: divan.github.io/posts/avoid_gotchas Commented Mar 20, 2017 at 23:22
  • That was a good documentation thanks! Commented Mar 21, 2017 at 1:38

1 Answer 1

3
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
}

There is a difference between a slice of pointers ([]*) and a pointer to a slice (*[]). You are returning a pointer to slice, whereas what you want is a slice of pointers. We can solve this by:

  • Updating your filterDevices signature to return a slice of pointers
  • Updating your make call to make a slice of pointers
  • Taking the address of e in your call to append (we want a slice of pointers to devices)
  • Not returning the address of the slice
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.