«указатель на интерфейс, а не интерфейс» - PullRequest
0 голосов
/ 26 мая 2018

Я изучаю Go и решил переписать MQTT-оркестратор, который я изначально написал на Python.Самая базовая часть работает отлично:

package main

import (
    "fmt"
    "time"
    "os"

    MQTT "github.com/eclipse/paho.mqtt.golang"
    log "github.com/sirupsen/logrus"
)

// definitions for a switch

type Switch struct {
    topic string
    state int
}

func allEvents(client MQTT.Client, msg MQTT.Message) {
    log.WithFields(log.Fields{"topic": msg.Topic(), "payload": fmt.Sprintf("%s", msg.Payload())}).Info()
}


func initMQTT() MQTT.Client {
    opts := MQTT.NewClientOptions()
    opts.AddBroker("tcp://mqtt.example.com:1883")
    opts.SetClientID("go-dispatcher")
    opts.SetCleanSession(true)
    client := MQTT.NewClient(opts)
    if token := client.Connect(); token.Wait() && token.Error() != nil {
        panic(token.Error())
    }
    log.Info("connected to MQTT broker")
    return client
}

func main() {
    // this is that part I want to modify later in the question
    c := initMQTT()
    if token := c.Subscribe("#", 0, allEvents); token.Wait() && token.Error() != nil {
        fmt.Println(token.Error())
        os.Exit(1)
    }

    time.Sleep(100000 * time.Hour)
}

Используя указатели в далеком прошлом с C, я хотел изменить программу, чтобы передать в части инициализации клиента по ссылке (больше как опыт обучения, первый код выглядит лучше для меня)

package main

import (
    "fmt"
    "time"
    "os"

    MQTT "github.com/eclipse/paho.mqtt.golang"
    log "github.com/sirupsen/logrus"
)

// definitions for a switch

type Switch struct {
    topic string
    state int
}

func allEvents(client MQTT.Client, msg MQTT.Message) {
    log.WithFields(log.Fields{"topic": msg.Topic(), "payload": fmt.Sprintf("%s", msg.Payload())}).Info()
}

// this time we get a pointer and do not return anything
func initMQTT(client *MQTT.Client) {
    opts := MQTT.NewClientOptions()
    opts.AddBroker("tcp://mqtt.example.com:1883")
    opts.SetClientID("go-dispatcher")
    opts.SetCleanSession(true)
    client = MQTT.NewClient(opts)
    if token := *client.Connect(); token.Wait() && token.Error() != nil {
        panic(token.Error())
    }
    log.Info("connected to MQTT broker")
}

func main() {
    // the client is defined in main()
    var c MQTT.Client
    // and passed by reference so that the function modifies it
    initMQTT(&c)
    if token := c.Subscribe("#", 0, allEvents); token.Wait() && token.Error() != nil {
        fmt.Println(token.Error())
        os.Exit(1)
    }

    time.Sleep(100000 * time.Hour)
}

Не удается скомпилировать с

# command-line-arguments
.\main.go:29:9: cannot use mqtt.NewClient(opts) (type mqtt.Client) as type *mqtt.Client in assignment:
    *mqtt.Client is pointer to interface, not interface
.\main.go:30:21: client.Connect undefined (type *mqtt.Client is pointer to interface, not interface)

Следуя совету формы другой вопрос , я пытался удалить & и * (вслепую, чтобы сказать правду) и получить ошибку во время выполнения

time="2018-05-26T21:02:20+02:00" level=info msg="connected to MQTT broker"
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0x604486]

goroutine 1 [running]:
main.main()
    D:/Seafile/dev/Go/src/perso/domotique.dispatcher/main.go:39 +0x36

Я думал, что, поскольку я определил c, я мог бы просто передать его какссылка, но, видимо, C-way здесь не тот? (обычно в примерах, которые я читал)

1 Ответ

0 голосов
/ 26 мая 2018

Это распространенное недоразумение.Поскольку вы определили c как значение, а не тип указателя, вы не можете изменить его, не переопределив.

Тот факт, что вы передали его адрес памяти, не позволяет вам изменить его.Это отличается от ряда других языков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...