"指向接口的指针,而不是接口"

时间:2018-05-26 19:04:46

标签: pointers go

我正在学习Go并决定重写我最初用Python编写的MQTT编排器。最基本的部分工作正常:

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)

按照another question的建议表单,我尝试删除&*(盲目地开始,说实话),并获得运行时错误

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 :(得分:0)

这是一种常见的误解。因为您已将c定义为值而不是指针类型,所以您无法在不重新定义的情况下对其进行修改。

您已通过其内存地址这一事实无法让您对其进行修改。这与许多其他语言不同。