SelectUpgrading Go V3 to V4

These docs are for version “3.16.1” of the Go SDK. To check out the docs for the latest version Click Here.
 

PubNub 4.0 for Go is our latest and greatest! Please click here for our PubNub 4.0 for Go docs and SDK.

PubNub 3.x for Go will encounter End Of Life (EOL) Jun 18, 19. All users currently on 3.x should begin migrating to 4.x. The 3.x SDK will continue to work. We will no longer support it and if you run into an issue, we will request that you upgrade to the latest version before solving the issue.

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(2).
        IncludeTimetoken(true).
        Reverse(true).
        Start(int64(0)).
        End(int64(1000)).
        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()