GoGo V3 to Go V4 Migration Guide

 

These docs are for PubNub 4.0 for Go which is our latest and greatest! For the docs of the older versions of the SDK, please check PubNub 3.0 for Go.

If you have questions about the PubNub for Go SDK, please contact us at support@pubnub.com.

  • V3 exposes github.com/pubnub/messaging
  • V4 exposes github.com/pubnub/go
  • V3 initiates via:
    import "github.com/pubnub/go/messaging"
    
    pubnub := messaging.NewPubnub("demo", "demo", "", "", false, "", nil)
  • V4 initiates via:
    import "github.com/pubnub/go"
    
    config := pubnub.NewConfig()
    config.SubscribeKey = "demo"
    config.PublishKey = "demo"
    config.SecretKey = "my-secret-key"
    config.CipherKey = "my-cipher-key"
    
    pn := pubnub.NewPubNub(config)
  • V3 return values via success/error channels:
    successChannel := make(chan []byte)
    errorChannel := make(chan []byte)
    
    go pubnub.History("my_channel", "", 100, 0, 0, false, false, successChannel, errorChannel)
    
    select {
        case response := <-successChannel:
            fmt.Println(string(response))
        case err := <-errorChannel:
            fmt.Println(string(err))
        case <-messaging.Timeout():
            fmt.Println("History() timeout")
    }
  • V4 return response/status/error values synchronously now:
    res, status, err := pn.History().
        Channel("my_channel").
        Count(100).
        Execute()
    
    if err != nil {
        panic(err)
    }
    
    fmt.Println(res)
    fmt.Println(status)
 
To execute a request asynchronously, wrap it with goroutine. Use channels to resolve a result.
The V4 SDK changes how PubNub handles callbacks for Subscribeand Presencecalls. Instead of passing the callback with every call, the SDK introduces a SubscribeCallback event, which is instantiated in a global manner. Furthermore, it receives various messages from PubNub, e.g. state and presence events, as well as published messages.
  • go func() {
            for {
                select {
                case status := <-listener.Status:
                    switch status.Category {
                    case pubnub.PNDisconnectedCategory:
                        // This event happens when radio / connectivity is lost
                    case pubnub.PNConnectedCategory:
                        // Connect event. You can do stuff like publish, and know you'll get it.
                        // Or just use the connected event to confirm you are subscribed for
                        // UI / internal notifications, etc
                        doneConnect <- true
                    case pubnub.PNReconnectedCategory:
                        // Happens as part of our regular operation. This event happens when
                        // radio / connectivity is lost, then regained.
                    }
                case message := <-listener.Message:
                    // Handle new message stored in message.message
                    if message.Channel != "" {
                        // Message has been received on channel group stored in
                        // message.Channel
                    } else {
                        // Message has been received on channel stored in
                        // message.Subscription
                    }
                    if msg, ok := message.Message.(map[string]interface{}); ok {
                        fmt.Println(msg["msg"])
                    }
                    /*
                        log the following items with your favorite logger
                            - message.Message
                            - message.Subscription
                            - message.Timetoken
                    */
     
                    donePublish <- true
                case <-listener.Presence:
                    // handle presence
                }
            }
        }()
  • config := pubnub.NewConfig()
    config.SubscribeKey = "demo"
    config.PublishKey = "demo"
    pn := pubnub.NewPubNub(config)
    listener := pubnub.NewListener()
    
    go func() {
            for {
                select {
                case status := <-listener.Status:
                    switch status.Category {
                    case pubnub.PNDisconnectedCategory:
                        // This event happens when radio / connectivity is lost
                    case pubnub.PNConnectedCategory:
                        // Connect event. You can do stuff like publish, and know you'll get it.
                        // Or just use the connected event to confirm you are subscribed for
                        // UI / internal notifications, etc
                        doneConnect <- true
                    case pubnub.PNReconnectedCategory:
                        // Happens as part of our regular operation. This event happens when
                        // radio / connectivity is lost, then regained.
                    }
                case message := <-listener.Message:
                    // Handle new message stored in message.message
                    if message.Channel != "" {
                        // Message has been received on channel group stored in
                        // message.Channel
                    } else {
                        // Message has been received on channel stored in
                        // message.Subscription
                    }
                    if msg, ok := message.Message.(map[string]interface{}); ok {
                        fmt.Println(msg["msg"])
                    }
                    /*
                        log the following items with your favorite logger
                            - message.Message
                            - message.Subscription
                            - message.Timetoken
                    */
      
                    donePublish <- true
                case <-listener.Presence:
                    // handle presence
                }
            }
        }()
    
    pn.AddListener(listener)
  • V3 subscribe:
    successChannel := make(chan []byte)
    errorChannel := make(chan []byte)
     
    go pubnub.Subscribe("my_channel", "", successChannel, false, errorChannel)
     
    for {
        select {
        case response := <-successChannel:
            var msg []interface{}
     
            err := json.Unmarshal(response, &msg)
            if err != nil {
                fmt.Println(err)
                return
            }
     
            switch m := msg[0].(type) {
            case float64:
                fmt.Println(msg[1].(string))
            case []interface{}:
                fmt.Printf("Received message '%s' on channel '%s'\n", m[0], msg[2])
                return
            default:
                panic(fmt.Sprintf("Unknown type: %T", m))
            }
     
        case err := <-errorChannel:
            fmt.Println(string(err))
        case <-messaging.SubscribeTimeout():
            fmt.Println("Subscribe() timeout")
        }
    }
  • V4 subscribe:
    pn.Subscribe().
        Channels([]string{"my-channel"}). // subscribe to channels
        Execute()
  • V3 unsubscribe:
    successChannel := make(chan []byte)
    errorChannel := make(chan []byte)
     
    go pubnub.Unsubscribe("my_channel", successChannel, errorChannel)
     
    select {
    case response := <-successChannel:
        fmt.Println(string(response))
    case err := <-errorChannel:
        fmt.Println(string(err))
    case <-messaging.Timeout():
        fmt.Println("Unsubscribe() timeout")
    }
  • V4 unsubscribe
    pn.Unsubscribe().
        Channels([]string{"my-channel"}).
        Execute()
  • V3 publish
    successChannel := make(chan []byte)
    errorChannel := make(chan []byte)
    message := struct { 
        First string `json:"first"` 
        Second string `json:"second"` 
        Age int `json:"age"` 
        Region string `json:"region"` 
    } { 
        "Robert", 
        "Plant", 
        59, 
        "UK", 
    }
    go pubnub.Publish(
        "my_channel", 
        message, 
        successChannel, 
        errorChannel
    )
    select
    { 
        case response := <-successChannel: 
            fmt.Println(string(response)) 
        case err := <-errorChannel: 
            fmt.Println(string(err)) 
        case <-messaging.Timeout(): 
            fmt.Println("Publish() timeout") 
    }
  • V4 publish
    message := struct { 
        First string `json:"first"` 
        Second string `json:"second"` 
        Age int `json:"age"` 
        Region string `json:"region"` 
    } { 
        "Robert", 
        "Plant", 
        59, 
        "UK", 
    }
    
    res, status, err := pn.Publish().
        Channel("my_channel").
        Message(message).
        Execute()
     
    // handle publish result
    fmt.Println(res, status, err)
  • V3 here now:
    successChannel := make(chan []byte)
    errorChannel := make(chan []byte)
     
    go pubnub.HereNow("my_channel", "", true, false, successChannel, errorChannel)
     
    select {
    case response := <-successChannel:
        fmt.Println(string(response))
    case err := <-errorChannel:
        fmt.Println(string(err))
    case <-messaging.Timeout():
        fmt.Println("HereNow() timeout")
    }
  • V4 here now:
    res, status, err := pn.HereNow().
        Channels([]string{"my-channel"}).
        IncludeUUIDs(true).
        Execute()
     
    for _, v := range res.Channels {
        fmt.Println("---")
        fmt.Println("Channel: ", v.ChannelName)
        fmt.Println("Occupancy: ", v.Occupancy)
        fmt.Println("Occupants")
     
        for _, v := range v.Occupants {
            fmt.Println("UUID: ", v.UUID, ", state: ", v.State)
        }
    }
     
    fmt.Println(status, err)
  • V3 presence:
    successChannel := make(chan []byte)
    errorChannel := make(chan []byte)
     
    go pubnub.Subscribe("my_channel-pnpres", "", successChannel, true, errorChannel)
     
    for {
        select {
        case response := <-successChannel:
            var msg []interface{}
     
            err := json.Unmarshal(response, &msg)
            if err != nil {
                fmt.Println(err)
                return
            }
     
            switch m := msg[0].(type) {
            case float64:
                fmt.Println(msg[1].(string))
            case []interface{}:
                fmt.Printf("Received message '%s' on channel '%s'\n", m[0], msg[2])
                return
            default:
                panic(fmt.Sprintf("Unknown type: %T", m))
            }
     
        case err := <-errorChannel:
            fmt.Println(string(err))
        case <-messaging.SubscribeTimeout():
            fmt.Println("Subscribe() timeout")
        }
    }
  • V4 presence:
    pn.Subscribe().
        Channels([]string{"my-channel"}).
        WithPresence(true).
        Execute()
  • V3 history:
    successChannel := make(chan []byte)
    errorChannel := make(chan []byte)
     
    go pubnub.History("my_channel", "", 100, 0, 0, false, false, successChannel, errorChannel)
     
    select {
        case response := <-successChannel:
            fmt.Println(string(response))
        case err := <-errorChannel:
            fmt.Println(string(err))
        case <-messaging.Timeout():
            fmt.Println("History() timeout")
    }
  • V4 history:
    res, status, err := pn.History().
        Channel("my_channel"). // where to fetch history from
        Count(100). // how many items to fetch
        Execute()
     
    fmt.Println(res, status, err)
  • V3 set state:
    successChannel := make(chan []byte)
    errorChannel := make(chan []byte)
     
    state := struct {
        First  string `json:"first"`
        Second string `json:"second"`
        Age    int    `json:"age"`
        Region string `json:"region"`
    }{
        "Robert",
        "Plant",
        59,
        "UK",
    }
     
    stateString, err := json.Marshal(state)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
     
    go p.SetUserStateJSON("my_channel", string(stateString), successChannel, errorChannel)
     
    select {
    case response := <-successChannel:
        fmt.Println(string(response))
    case err := <-errorChannel:
        fmt.Println(string(err))
    case <-messaging.Timeout():
        fmt.Println("SetUserStateJSON() timeout")
    }
  • V4 set state:
    state := struct {
        First  string `json:"first"`
        Second string `json:"second"`
        Age    int    `json:"age"`
        Region string `json:"region"`
    }{
        "Robert",
        "Plant",
        59,
        "UK",
    }
    
    res, status, err := pn.SetState().
        Channels([]string{"my_channel"}).
        State(state).
        Execute()
     
    fmt.Println(res, status, err)
  • V3 get state:
    successChannel := make(chan []byte)
    errorChannel := make(chan []byte)
     
    go p.GetUserState("my_channel", "", successChannel, errorChannel)
     
    select {
    case response := <-successChannel:
        fmt.Println(string(response))
    case err := <-errorChannel:
        fmt.Println(string(err))
    case <-messaging.Timeout():
        fmt.Println("GetUserState() timeout")
    }
  • V4 get state:
    res, status, err := pn.GetState().
        Channels([]string{"my_channel"}).
        Execute()
     
    fmt.Println(res, status, err)
  • V3 time
    successChannel := make(chan []byte)
    errorChannel := make(chan []byte)
     
    go pubnub.GetTime(successChannel, errorChannel)
     
    select {
        case msg := <-successChannel:
            time := strings.Trim(string(msg), "[]")
            fmt.Println(time)
        case err := <-errorChannel:
            fmt.Println(string(err))
        case <-messaging.Timeout():
            fmt.Println("GetTime() timeout")
    }
  • V4 time
    res, status, err := pn.Time().Execute()
     
    fmt.Println(res, status, err)
  • V3 destroy
    pubnub.Abort()
  • V4 destroy
    pn.Destroy()