• Go 感受回调函数的魅力


    Go 感受回调函数的魅力

    在用mqtt的SDK时候,感觉回调一脸蒙蔽,在自己实现之后,还是有点意思的

    官方sdk原始代码

    /*
     * Copyright (c) 2013 IBM Corp.
     *
     * All rights reserved. This program and the accompanying materials
     * are made available under the terms of the Eclipse Public License v1.0
     * which accompanies this distribution, and is available at
     * http://www.eclipse.org/legal/epl-v10.html
     *
     * Contributors:
     *    Seth Hoenig
     *    Allan Stockdill-Mander
     *    Mike Robertson
     */
    
    package main
    
    import (
    	"fmt"
    	"log"
    	"os"
    	"time"
    
    	"github.com/eclipse/paho.mqtt.golang"
    )
    
    var f mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
    	fmt.Printf("TOPIC: %s
    ", msg.Topic())
    	fmt.Printf("MSG: %s
    ", msg.Payload())
    }
    
    func main() {
    	mqtt.DEBUG = log.New(os.Stdout, "", 0)
    	mqtt.ERROR = log.New(os.Stdout, "", 0)
    	opts := mqtt.NewClientOptions().AddBroker("tcp://iot.eclipse.org:1883").SetClientID("gotrivial")
    	opts.SetKeepAlive(2 * time.Second)
    	opts.SetDefaultPublishHandler(f)
    	opts.SetPingTimeout(1 * time.Second)
    
    	c := mqtt.NewClient(opts)
    	if token := c.Connect(); token.Wait() && token.Error() != nil {
    		panic(token.Error())
    	}
    
    	// 注意下面的f
    	if token := c.Subscribe("go-mqtt/sample", 0, f); token.Wait() && token.Error() != nil {
    		fmt.Println(token.Error())
    		os.Exit(1)
    	}
    
    	for i := 0; i < 5; i++ {
    		text := fmt.Sprintf("this is msg #%d!", i)
    		token := c.Publish("go-mqtt/sample", 0, false, text)
    		token.Wait()
    	}
    
    	time.Sleep(6 * time.Second)
    
    	if token := c.Unsubscribe("go-mqtt/sample"); token.Wait() && token.Error() != nil {
    		fmt.Println(token.Error())
    		os.Exit(1)
    	}
    
    	c.Disconnect(250)
    
    	time.Sleep(1 * time.Second)
    }
    

    我自己还原的

    mq.go

    package mq
    
    type Sub func(c *Client, mgs []byte)
    
    type Client struct {
    	SubData chan []byte
    }
    
    func NewClient() *Client {
    	return &Client{SubData:make(chan []byte, 1)}
    }
    
    func (c *Client)Subscribe(topic string, qos int, fn Sub)  {
    	go func() {
    		for {
    			select {
    			case data := <- c.SubData:
    				// 可以在这里面进行进一步处理
    				fn(c, data)
    			}
    		}
    	}()
    }
    
    

    main.go

    package main
    
    import (
    	"aaa/mq"
    	"encoding/json"
    	"fmt"
    	"log"
    	"time"
    )
    
    const _defaultTopic  = "+/a"
    
    type Data struct {
    	Topic string
    	PayLoad []byte
    }
    
    var callback mq.Sub = func(client *mq.Client, msg []byte) {
    	var d Data
    	err := json.Unmarshal(msg,&d)
    	if err != nil {
    		log.Println(err)
    	}
    
    	fmt.Println("获取的topic", d.Topic)
    	fmt.Println("获取的数据", string(d.PayLoad))
    }
    
    func main()  {
    	client := mq.NewClient()
    	client.Subscribe(_defaultTopic, 1, callback)
    
    	// 模拟pub数据
    	for {
    		d := Data{
    			Topic:   _defaultTopic,
    			PayLoad: []byte(time.Now().String()),
    		}
    
    		marshal, err := json.Marshal(d)
    		if err != nil {
    			log.Println(err)
    		}
    
    		client.SubData<- marshal
    		time.Sleep(time.Millisecond * 500)
    	}
    }
    

    理解

    回调函数在结构上出来,传进去的参数让用户自己处理

    有意思的回调理解

    打个比方,有一家旅馆提供叫醒服务,但是要求旅客自己决定叫醒的方法。可以是打客房电话,也可以是派服务员去敲门,睡得死怕耽误事的,还可以要求往自己头上浇盆水。这里,“叫醒”这个行为是旅馆提供的,相当于库函数,但是叫醒的方式是由旅客决定并告诉旅馆的,也就是回调函数。而旅客告诉旅馆怎么叫醒自己的动作,也就是把回调函数传入库函数的动作,称为登记回调函数

  • 相关阅读:
    安装wampserver2时出现的问题
    微信相关信息
    YII CDbCriteria总结
    discuz@功能的代码
    音乐搜索并生成播放功能
    php生成json和js解析json
    Discuz!提取文章标签
    ⑦ vue项目结构study
    ⑤ elementui 使用字符填充table空白表格项
    ④ keep-alive缓存组件,操作之后需要重新获取数据--activated
  • 原文地址:https://www.cnblogs.com/maomaomaoge/p/14632302.html
Copyright © 2020-2023  润新知