---
source_url: https://www.pubnub.com/docs/sdks/go/api-reference/publish-and-subscribe
title: Publish/Subscribe API for Go SDK
updated_at: 2026-06-18T11:27:37.884Z
sdk_name: PubNub Go SDK
sdk_version: v9.0.1
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Publish/Subscribe API for Go SDK

PubNub Go SDK, use the latest version: v9.0.1

Install:

```bash
go get github.com/pubnub/go/v9@v9.0.1
```

PubNub delivers messages worldwide in less than 30 ms. Send a message to one recipient or broadcast to thousands of subscribers.

For higher-level conceptual details on publishing and subscribing, refer to [Connection Management](https://www.pubnub.com/docs/general/setup/connection-management) and to [Publish Messages](https://www.pubnub.com/docs/general/messages/publish).

## Publish

The `Publish()` method sends a message to all channel subscribers. PubNub replicates the message across its points of presence and delivers it to all subscribed clients on that channel.

### Prerequisites and limitations

* You must [initialize PubNub](https://www.pubnub.com/docs/sdks/go/api-reference/configuration#configuration) with the `publishKey`.
* You don't have to be subscribed to a channel to publish to it.
* You cannot publish to multiple channels simultaneously.

### Security

Secure messages with Transport Layer Security (TLS) or Secure Sockets Layer (SSL) by setting `ssl` to `true` during [initialization](https://www.pubnub.com/docs/sdks/go/api-reference/configuration#configuration). You can also [encrypt](https://www.pubnub.com/docs/sdks/go/api-reference/configuration#cryptomodule) messages.

### Message data

The message can contain any JavaScript Object Notation (JSON)-serializable data (objects, arrays, integers, strings). Avoid special classes or functions. Strings can include any UTF‑8 characters.

:::warning Don't JSON serialize
You should not JSON serialize the `message` and `meta` parameters when sending signals, messages, or files as the serialization is automatic. Pass the full object as the message/meta payload and let PubNub handle everything.
:::

### Size

The maximum message size is 32 KiB. This includes the escaped character count and the channel name. Aim for under 1,800 bytes for optimal performance.

If your message exceeds the limit, you'll receive a `Message Too Large` error. To learn more or calculate payload size, see [Message size limits](https://www.pubnub.com/docs/general/messages/publish#message-size-limit).

:::tip Need larger messages?
Our platform is optimized for payloads up to 32 KiB. PubNub supports larger messages, but increasing the limit requires a verification of compatibility with your use case.
Talk to [our team](https://www.pubnub.com/company/contact-sales/) to discuss increasing the message size limit for your use case.
:::

### Publish rate

You can publish as fast as bandwidth allows. There is a [soft throughput limit](https://www.pubnub.com/docs/general/setup/limits) because messages may drop if subscribers can't keep up.

For example, publishing 200 messages at once may cause the first 100 to drop if a subscriber hasn't received any yet. The in-memory queue stores only 100 messages.

### Custom message type

You can optionally provide the `CustomMessageType` parameter to add your business-specific label or category to the message, for example `text`, `action`, or `poll`.

### Best practices

* Publish to a channel serially (not concurrently).
* Verify a success return code (for example, `[1,"Sent","136074940..."]`).
* Publish the next message only after a success return code.
* On failure (`[0,"blah","<timetoken>"]`), retry.
* Keep the in-memory queue under 100 messages to avoid drops.
* Throttle bursts to meet latency needs (for example, no more than 5 messages per second).

### Method(s)

To `Publish a message` you can use the following method(s) in the Go SDK:

```go
pn.Publish().
    Message(interface{}).
    Channel(string).
    ShouldStore(bool).
    UsePost(bool).
    Meta(interface{}).
    QueryParam(queryParam).
    CustomMessageType(string).
    Execute()
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| Message | interface | Yes |  | The payload |
| Channel | string | Yes |  | Destination of `Message` (channel ID) |
| ShouldStore | bool | Optional | `account default` | Store in history |
| UsePost | bool | Optional | `false` | Use POST to `Publish` |
| Meta | interface | Optional | `null` | Meta data object which can be used with the filtering ability |
| TTL | int | Optional |  | Set a per message time to live in Message Persistence. If ShouldStore = true, and TTL = 0, the message is stored with no expiry time., If ShouldStore = true and TTL = X (X is an Integer value), the message is stored with an expiry time of X hours unless you have message retention set to Unlimited on your keyset configuration in the Admin Portal., If ShouldStore = false, the TTL parameter is ignored., If TTL is not specified, then expiration of the message defaults back to the expiry value for the key. |
| QueryParam | map[string]string | Optional | `nil` | QueryParam accepts a map, the keys and values of the map are passed as the query string parameters of the URL called by the API. |
| CustomMessageType | string | Optional |  | A case-sensitive, alphanumeric string from 3 to 50 characters describing the business-specific label or category of the message. Dashes `-` and underscores `_` are allowed. The value cannot start with special characters or the string `pn_` or `pn-`. Examples: `text`, `action`, `poll`. |

### Sample code

:::tip Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
:::

#### Publish a message to a channel

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_simplePublish demonstrates basic message publishing
func Example_simplePublish() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo" // Replace with your subscribe key
	config.PublishKey = "demo"   // Replace with your publish key

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	response, status, err := pn.Publish().
		Channel("my-channel").
		Message("Hello World!").
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if response.Timestamp > 0 && status.StatusCode == 200 {
		fmt.Println("Message published successfully")
	}

	// Output:
	// Message published successfully
}
```

:::note Subscribe to the channel
Before running the above publish example, either using the [Debug Console](https://www.pubnub.com/docs/console/) or in a separate script running in a separate terminal window, [subscribe to the same channel](#subscribe) that is being published to.
:::

### Response

| Method | Description |
| --- | --- |
| `Timestamp`Type: int | An `int` representation of the timetoken when the message was published |

### Other examples

#### Publish with metadata

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_publishWithMetadata demonstrates publishing with custom metadata
func Example_publishWithMetadata() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Create metadata object
	metadata := map[string]interface{}{
		"sender":   "user-123",
		"language": "english",
	}

	// Publish message with metadata
	response, status, err := pn.Publish().
		Channel("my-channel").
		Message("Hello with metadata!").
		Meta(metadata). // Add metadata
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if response.Timestamp > 0 && status.StatusCode == 200 {
		fmt.Println("Message with metadata published successfully")
	}

	// Output:
	// Message with metadata published successfully
}
```

#### Publish array

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_publishArray demonstrates publishing an array with metadata
func Example_publishArray() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Publish an array message with metadata and custom message type
	response, status, err := pn.Publish().
		Channel("my-channel").
		Message([]string{"Hello", "there"}).
		Meta([]string{"1a", "2b", "3c"}).
		CustomMessageType("text-message").
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if response.Timestamp > 0 && status.StatusCode == 200 {
		fmt.Println("Array message published successfully")
	}

	// Output:
	// Array message published successfully
}
```

#### Store the published message for 24 hours

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_publishWithTTL demonstrates publishing with message expiration
func Example_publishWithTTL() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Publish message with TTL (Time To Live)
	response, status, err := pn.Publish().
		Channel("my-channel").
		Message("This message expires in 24 hours").
		TTL(24).           // Message expires after 24 hours
		ShouldStore(true). // Ensure message is stored
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if response.Timestamp > 0 && status.StatusCode == 200 {
		fmt.Println("Message with TTL published successfully")
	}

	// Output:
	// Message with TTL published successfully
}
```

#### Push payload helper

You can use the helper method as an input to the `Message` parameter, to format the payload for publishing [Push](https://www.pubnub.com/docs/general/push/send) messages. For more info on the helper method, check [Create Push Payload Helper Section](https://www.pubnub.com/docs/sdks/go/api-reference/misc#create-push-payload)

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"

	pubnub "github.com/pubnub/go/v9"
)

// Example_createPushPayloadCombined demonstrates creating a combined push payload for both APNS and FCM
func Example_createPushPayloadCombined() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Create APNS payload
	apnsPayload := pubnub.PNAPNSData{
		APS: pubnub.PNAPSData{
			Alert: "New message!",
			Badge: 1,
			Sound: "default",
		},
	}

	// Create FCM payload
	fcmPayload := pubnub.PNFCMData{
		Data: pubnub.PNFCMDataFields{
			Summary: "New message!",
		},
	}

	// Create common payload for regular PubNub subscribers
	commonPayload := map[string]interface{}{
		"text":      "New message!",
		"timestamp": "2024-01-01T00:00:00Z",
	}

	// Build combined push payload
	pushPayload := pn.CreatePushPayload().
		SetAPNSPayload(apnsPayload, nil).
		SetFCMPayload(fcmPayload).
		SetCommonPayload(commonPayload).
		BuildPayload()

	// Publish the combined push payload
	response, status, err := pn.Publish().
		Channel("notification-channel").
		Message(pushPayload).
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if status.StatusCode == 200 && response.Timestamp > 0 {
		fmt.Println("Combined push payload published successfully")
	}

	// Output:
	// Combined push payload published successfully
}
```

## Fire

The fire endpoint sends a message to Functions event handlers and [Illuminate](https://www.pubnub.com/docs/illuminate/business-objects/external-data-sources). The message goes directly to handlers registered on the target channel and triggers their execution. The handler can read the request body. Messages sent via `fire()` aren't replicated to subscribers and aren't stored in history.

### Method(s)

To `Fire a message` you can use the following method(s) in the Go SDK:

```go
pn.Fire().
    Message(interface{}).
    Channel(string).
    UsePost(bool).
    Meta(interface{}).
    QueryParam(queryParam).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Message` *Type: interfaceDefault: n/a | The payload |
| `Channel` *Type: stringDefault: n/a | Destination of `Message` (channel ID) |
| `UsePost`Type: boolDefault: `false` | Use POST to `Publish` |
| `Meta`Type: interfaceDefault: `null` | Meta data object which can be used with the filtering ability |
| `TTL`Type: intDefault: n/a | Set a per message time to live in Message Persistence. If ShouldStore = true, and TTL = 0, the message is stored with no expiry time., If ShouldStore = true and TTL = X (X is an Integer value), the message is stored with an expiry time of X hours unless you have message retention set to Unlimited on your keyset configuration in the Admin Portal., If ShouldStore = false, the TTL parameter is ignored., If TTL is not specified, then expiration of the message defaults back to the expiry value for the key. |
| `QueryParam`Type: map[string]stringDefault: `nil` | QueryParam accepts a map, the keys and values of the map are passed as the query string parameters of the URL called by the API. |

### Sample code

#### Fire a message to a channel

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_fire demonstrates fire operation (publish without storage)
func Example_fire() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Fire message (not stored in history, lower latency)
	response, status, err := pn.Fire().
		Channel("my-channel").
		Message("Ephemeral message").
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if response.Timestamp > 0 && status.StatusCode == 200 {
		fmt.Println("Fire message sent successfully")
	}

	// Output:
	// Fire message sent successfully
}
```

#### Fire with metadata

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_fireWithMetadata demonstrates fire operation with custom metadata
func Example_fireWithMetadata() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Fire message with metadata (not stored in history)
	response, status, err := pn.Fire().
		Channel("my-channel").
		Message("test").
		Meta(map[string]interface{}{
			"name":      "important-event",
			"timestamp": 1234567890,
		}).
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if response.Timestamp > 0 && status.StatusCode == 200 {
		fmt.Println("Fire message with metadata sent successfully")
	}

	// Output:
	// Fire message with metadata sent successfully
}
```

## Signal

The `signal()` function sends a signal to all subscribers of a channel.

By default, signals are limited to a message payload size of `64` bytes. This limit applies only to the payload, and not to the URI or headers. If you require a larger payload size, please [contact support](https://www.pubnub.com/docs/mailto:support@pubnub.com).

### Method(s)

To `Signal a message` you can use the following method(s) in the Go SDK:

```go
pubnub.Signal().
    Message(interface{}).
    Channel(string).
    CustomMessageType(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Message` *Type: interfaceDefault: n/a | The payload. |
| `Channel` *Type: stringDefault: n/a | Destination of `Message` (channel ID). |
| `CustomMessageType`Type: stringDefault: n/a | A case-sensitive, alphanumeric string from 3 to 50 characters describing the business-specific label or category of the message. Dashes `-` and underscores `_` are allowed. The value cannot start with special characters or the string `pn_` or `pn-`. Examples: `text`, `action`, `poll`. |

### Sample code

#### Signal a message to a channel

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_signal demonstrates sending signals (lightweight messages)
func Example_signal() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Send signal (lightweight, not stored, up to 64 bytes)
	response, status, err := pn.Signal().
		Channel("my-channel").
		Message("typing...").
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if response.Timestamp > 0 && status.StatusCode == 200 {
		fmt.Println("Signal sent successfully")
	}

	// Output:
	// Signal sent successfully
}
```

### Response

| Method | Description |
| --- | --- |
| `Timestamp`Type: int | An `int` representation of the timetoken when Signal was sent |

## Subscribe

### Receive messages

Your app receives messages and events via event listeners. The event listener is a single point through which your app receives all the messages, signals, and events that are sent in any channel you are subscribed to.

For more information about adding a listener, refer to the [Event Listeners](https://www.pubnub.com/docs/sdks/go/api-reference/configuration#event-listeners) section.

:::note No built-in event throttling
The PubNub SDK delivers every incoming event to your listener as it arrives — there is no built-in throttling or rate-limiting on the subscriber side. If you need to control how often your application processes events, wrap your listener callback with a throttle or debounce utility from your language or framework ecosystem.
To reduce the number of messages delivered to your client in the first place, use [Subscribe Filters](https://www.pubnub.com/docs/general/channels/subscribe-filters) to filter messages server-side before they reach your listener.
:::

### Description

This function causes the client to create an open TCP socket to the PubNub Real-Time Network and begin listening for messages on a specified `channel` ID. To subscribe to a `channel` ID the client must send the appropriate `SubscribeKey` at initialization. By default a newly subscribed client will only receive messages published to the channel after the `Subscribe()` call completes.

:::tip Connectivity notification
You can be notified of connectivity via the `envelope.status`. By waiting for the `envelope.status` to return before attempting to publish, you can avoid a potential race condition on clients that subscribe and immediately publish messages before the subscribe has completed.
:::

Using Go SDK, if a client becomes disconnected from a channel, it can automatically attempt to reconnect to that channel and retrieve any available messages that were missed during that period by setting `restore` to `true`. By default a client will attempt to reconnect after exceeding a `320` second connection timeout.

:::warning Unsubscribing from all channels
**Unsubscribing** from all channels, and then **subscribing** to a new channel Y is not the same as subscribing to channel Y and then unsubscribing from the previously-subscribed channel(s). Unsubscribing from all channels resets the last-received `timetoken` and thus, there could be some gaps in the subscription that may lead to message loss.
:::

### Method(s)

To `Subscribe to a channel` you can use the following method(s) in the Go SDK:

```go
pn.Subscribe().
    Channels([]string).
    ChannelGroups([]string).
    Timetoken(int64).
    WithPresence(bool).
    QueryParam(queryParam).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Channels`Type: []string | Subscribe to `channels`, Either `channel` ID or `channel_group` is required. |
| `ChannelGroups`Type: []string | Subscribe to `channel_groups`, Either `channel` ID or `channel_group` is required. |
| `Timetoken`Type: int64 | Pass a `timetoken`. |
| `WithPresence`Type: bool | Also subscribe to related presence information. For information on how to receive presence events and what those events are, refer to [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events#subscribe-to-presence-channel). |
| `QueryParam`Type: map[string]string | QueryParam accepts a map, the keys and values of the map are passed as the query string parameters of the URL called by the API. |

### Sample code

Subscribe to a channel:

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_subscribe demonstrates basic channel subscription
func Example_subscribe() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Create listener to handle incoming messages
	listener := pubnub.NewListener()

	// Create a done channel to stop the goroutine when needed
	done := make(chan bool)

	go func() {
		for {
			select {
			case status := <-listener.Status:
				// Handle connection status changes
				switch status.Category {
				case pubnub.PNConnectedCategory:
					fmt.Println("Connected to PubNub")
				case pubnub.PNReconnectedCategory:
					fmt.Println("Reconnected to PubNub")
				case pubnub.PNDisconnectedCategory:
					fmt.Println("Disconnected from PubNub")
				}

			case message := <-listener.Message:
				// Handle received messages
				fmt.Printf("Received message: %v on channel: %s\n",
					message.Message, message.Channel)

			case <-done:
				// Stop the goroutine when done signal is received
				return
			}
		}
	}()

	// Add listener and subscribe to channel
	pn.AddListener(listener)

	pn.Subscribe().
		Channels([]string{"my-channel"}).
		Execute()

	fmt.Println("Subscribed to channel")

	// When done, unsubscribe and stop goroutine
	pn.UnsubscribeAll()
	close(done)

	// snippet.hide
	// Small delay to ensure cleanup completes before next example
	time.Sleep(100 * time.Millisecond)
	// snippet.show

}
```

### Response

:::note PNMessage
`PNMessage` is returned in the [Listeners](https://www.pubnub.com/docs/sdks/go/api-reference/configuration#event-listeners)
:::

The `Subscribe()` operation returns a `PNStatus` which contains the following operations:

| Property Name | Type | Description |
| --- | --- | --- |
| `Category` | `StatusCategory` | See the [Go SDK listener categories](https://www.pubnub.com/docs/sdks/go/status-events). |
| `Error` | bool | This is `true` if an error occurred in the execution of the operation. |
| `ErrorData` | error | Error data of the exception (if `Error` is `true`). |
| `StatusCode` | int | Status code of the execution. |
| `Operation` | OperationType | Operation type of the request. |

The `Subscribe()` operation returns a `PNMessage` for messages, for both `Publish` and `Signal` messages, which contains the following operations:

| Method | Description |
| --- | --- |
| `Message`Type: interface | The message sent on the `channel` ID. |
| `Channel`Type: string | The channel ID on which the message was received. |
| `Subscription`Type: string | The channel group or wildcard subscription match (if exists). |
| `Timetoken`Type: int64 | `Timetoken` for the message. |
| `UserMetadata`Type: interface | User `metadata`. |
| `SubscribedChannel`Type: string | Current `subscribed channel`. |
| `Publisher`Type: string | UUID of `publisher`. |

The `Subscribe()` operation returns a `PNPresence` for messages which contains the following operations:

| Method | Description |
| --- | --- |
| `Event`Type: string | Events like `join`, `leave`, `timeout`, `state-change`. |
| `UUID`Type: string | `UUID` for event. |
| `Timestamp`Type: int64 | `Timestamp` for event. |
| `Occupancy`Type: int | Current `occupancy`. |
| `Subscription`Type: string | Message has been received on the `Channel` ID. |
| `Timetoken`Type: int64 | `Timetoken` of the message. |
| `State`Type: interface | `State` of the UUID. |
| `UserMetadata`Type: map[string]interface | User `metadata`. |
| `SubscribedChannel`Type: string | Current `subscribed channel`. |
| `Channel`Type: string | The `channel` ID for which the message belongs. |

The `Subscribe()` operation returns a `PNUUIDEvent` for UUID Events which contains the following operations:

| Method | Description |
| --- | --- |
| `Event`Type: PNObjectsEvent | Events like `PNObjectsEventRemove`, `PNObjectsEventSet`. |
| `Timestamp`Type: string | `Timestamp` for event. |
| `Subscription`Type: string | Event has been received on the `Channel` ID. |
| `SubscribedChannel`Type: string | Current `subscribed channel`. |
| `Channel`Type: string | The `channel` ID for which the event belongs. |
| `UUID`Type: string | The UUID. |
| `Name`Type: string | Display name for the space. |
| `ExternalID`Type: string | User's identifier in an external system |
| `ProfileURL`Type: string | The URL of the user's profile picture |
| `Email`Type: string | The user's email address. |
| `Custom`Type: map[string]interface | Map of string and interface with supported data types. |
| `Updated`Type: string | Last updated date. |
| `ETag`Type: string | The ETag. |

The `Subscribe()` operation returns a `PNChannelEvent` for Channel Events which contains the following operations:

| Method | Description |
| --- | --- |
| `Event`Type: PNObjectsEvent | Events like `PNObjectsEventRemove`, `PNObjectsEventSet`. |
| `Timestamp`Type: string | `Timestamp` for event. |
| `Subscription`Type: string | Event has been received on the `Channel` ID. |
| `SubscribedChannel`Type: string | Current `subscribed channel`. |
| `Channel`Type: string | The `channel` ID for which the event belongs. |
| `ChannelID`Type: string | The Channel ID. |
| `Name`Type: string | Display name for the space. |
| `Description`Type: string | Description of the space. |
| `Custom`Type: map[string]interface | Map of string and interface with supported data types. |
| `Updated`Type: string | Last updated date. |
| `ETag`Type: string | The ETag. |

The `Subscribe()` operation returns a `PNMembershipEvent` for Membership Events which contains the following operations:

| Method | Description |
| --- | --- |
| `Event`Type: PNObjectsEvent | Events like `PNObjectsEventRemove`, `PNObjectsEventSet`. |
| `Timestamp`Type: string | `Timestamp` for event. |
| `Subscription`Type: string | Event has been received on the `Channel` ID. |
| `SubscribedChannel`Type: string | Current `subscribed channel`. |
| `Channel`Type: string | The `channel` ID for which the event belongs. |
| `ChannelID`Type: string | The Channel ID. |
| `UUID`Type: string | The UUID. |
| `Custom`Type: map[string]interface | Map of string and interface with supported data types. |

The `Subscribe()` operation returns a `PNMessageActionsEvent` for Message Actions Events which contains the following operations:

| Method | Description |
| --- | --- |
| `Event`Type: PNMessageActionsEventType | Events like `PNMessageActionsAdded`, `PNMessageActionsRemoved`. |
| `Data`Type: PNMessageActionsResponse | [Message Actions](https://www.pubnub.com/docs/sdks/go/api-reference/message-actions) for event. |
| `Subscription`Type: string | Event has been received on the `Channel` ID. |
| `SubscribedChannel`Type: string | Current `subscribed channel`. |
| `Channel`Type: string | The `channel` ID for which the event belongs. |

### Other examples

#### Basic subscribe with logging

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_subscribeBasicWithLogging demonstrates basic subscription setup
func Example_subscribeBasicWithLogging() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.PublishKey = "demo"
	config.SubscribeKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Subscribe to a channel
	pn.Subscribe().
		Channels([]string{"my-channel"}).
		Execute()

	fmt.Println("Subscribed to my-channel")

	// Cleanup
	pn.UnsubscribeAll()

	// snippet.hide
	// Small delay to ensure cleanup completes before next example
	time.Sleep(100 * time.Millisecond)
	// snippet.show

	// Output:
	// Subscribed to my-channel
}
```

#### Subscribing to multiple channels

It's possible to subscribe to more than one channel using the [Multiplexing](https://www.pubnub.com/docs/general/channels/subscribe#channel-multiplexing) feature. The example shows how to do that using an array to specify the channel names.

:::note Alternative subscription methods
You can also use [Wildcard Subscribe](https://www.pubnub.com/docs/general/channels/subscribe#wildcard-subscribe) and [Channel Groups](https://www.pubnub.com/docs/general/channels/subscribe#channel-groups) to subscribe to multiple channels at a time. To use these features, the *Stream Controller* add-on must be enabled on your keyset in the [Admin Portal](https://admin.pubnub.com).
:::

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_subscribeMultiple demonstrates subscribing to multiple channels
func Example_subscribeMultiple() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	listener := pubnub.NewListener()

	// Create a done channel to stop the goroutine when needed
	done := make(chan bool)

	go func() {
		for {
			select {
			case status := <-listener.Status:
				if status.Category == pubnub.PNConnectedCategory {
					fmt.Println("Connected to channels")
				}

			case message := <-listener.Message:
				fmt.Printf("Received on %s: %v\n",
					message.Channel, message.Message)

			case <-done:
				// Stop the goroutine when done signal is received
				return
			}
		}
	}()

	pn.AddListener(listener)

	// Subscribe to multiple channels at once
	pn.Subscribe().
		Channels([]string{"channel-1", "channel-2", "channel-3"}).
		Execute()

	fmt.Println("Subscribed to multiple channels")

	// When done, unsubscribe and stop goroutine
	pn.UnsubscribeAll()
	close(done)

	// snippet.hide
	// Small delay to ensure cleanup completes before next example
	time.Sleep(100 * time.Millisecond)
	// snippet.show

	// Output:
	// Subscribed to multiple channels
}
```

#### Subscribing to a Presence channel

:::warning Requires Presence
This method requires that the Presence add-on is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/). For information on how to receive presence events and what those events are, refer to [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events#subscribe-to-presence-channel).
:::

For any given channel there is an associated Presence channel. You can subscribe directly to the channel by appending `-pnpres` to the channel name. For example the channel named `my_channel` would have the presence channel named `my_channel-pnpres`.

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_subscribeWithPresence demonstrates subscription with presence enabled
func Example_subscribeWithPresence() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	listener := pubnub.NewListener()

	// Create a done channel to stop the goroutine when needed
	done := make(chan bool)

	go func() {
		for {
			select {
			case status := <-listener.Status:
				if status.Category == pubnub.PNConnectedCategory {
					fmt.Println("Connected with presence")
				}

			case message := <-listener.Message:
				// Handle regular messages
				fmt.Printf("Message: %v\n", message.Message)

			case presence := <-listener.Presence:
				// Handle presence events (join, leave, timeout)
				fmt.Printf("Presence event: %s for UUID: %s\n",
					presence.Event, presence.UUID)

			case <-done:
				// Stop the goroutine when done signal is received
				return
			}
		}
	}()

	pn.AddListener(listener)

	// Subscribe with presence events enabled
	pn.Subscribe().
		Channels([]string{"my-channel"}).
		WithPresence(true). // Enable presence events
		Execute()

	fmt.Println("Subscribed with presence")

	// When done, unsubscribe and stop goroutine
	pn.UnsubscribeAll()
	close(done)

	// snippet.hide
	// Small delay to ensure cleanup completes before next example
	time.Sleep(100 * time.Millisecond)
	// snippet.show

	// Output:
	// Subscribed with presence
}
```

#### Sample Responses

##### Join event

```go
if presence.Event == "join" {
    presence.UUID // 175c2c67-b2a9-470d-8f4b-1db94f90e39e
    presence.Timestamp // 1345546797
    presence.Occupancy // 2
}
```

##### Leave event

```json
if presence.Event == "leave" {
    presence.UUID // 175c2c67-b2a9-470d-8f4b-1db94f90e39e
    presence.Timestamp // 1345546797
    presence.Occupancy // 2
}
```

##### Timeout event

```json
if presence.Event == "timeout" {
    presence.UUID // 175c2c67-b2a9-470d-8f4b-1db94f90e39e
    presence.Timestamp // 1345546797
    presence.Occupancy // 2
}
```

##### State change event

```json
if presence.Event == "state-change" {
    presence.Timestamp
    presence.Occupancy
}
```

##### Interval event

```json
if presence.Event == "interval" {
    presence.UUID // 175c2c67-b2a9-470d-8f4b-1db94f90e39e
    presence.Timestamp // 1345546797
    presence.Occupancy // 2
}
```

When a channel is in interval mode with `presence_deltas` `pnconfig` flag enabled, the interval message may also include the following fields which contain an array of changed UUIDs since the last interval message.

* joined
* left
* timedout

For example, this interval message indicates there were 2 new UUIDs that joined and 1 timed out UUID since the last interval:

```json
if presence.Event == "interval" {
    presence.Occupancy // # users in channel
    presence.Join // [uuid1 uuid2]
    presence.Timeout //[uuid3]
    presence.Timestamp // unix timestamp
}
```

If the full interval message is greater than `30 KB` (since the max publish payload is `∼32 KiB`), none of the extra fields will be present. Instead there will be a `here_now_refresh` boolean field set to `true`. This indicates to the user that they should do a `hereNow` request to get the complete list of users present in the channel.

#### Wildcard subscribe to channels

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/) (with Enable Wildcard Subscribe checked). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

Wildcard subscribes allow the client to subscribe to multiple channels using wildcard. For example, if you subscribe to `a.*` you will get all messages for `a.b`, `a.c`, `a.x`. The wildcarded `*` portion refers to any portion of the channel string name after the `dot (.)`.

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_subscribeWildcard demonstrates wildcard channel subscription
func Example_subscribeWildcard() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	listener := pubnub.NewListener()

	// Create a done channel to stop the goroutine when needed
	done := make(chan bool)

	go func() {
		for {
			select {
			case status := <-listener.Status:
				if status.Category == pubnub.PNConnectedCategory {
					fmt.Println("Connected to wildcard channels")
				}

			case message := <-listener.Message:
				fmt.Printf("Received on %s: %v\n",
					message.Channel, message.Message)

			case <-done:
				// Stop the goroutine when done signal is received
				return
			}
		}
	}()

	pn.AddListener(listener)

	// Subscribe to wildcard pattern (matches room.*, room.1, room.2, etc.)
	pn.Subscribe().
		Channels([]string{"room.*"}).
		Execute()

	fmt.Println("Subscribed to wildcard channels")

	// When done, unsubscribe and stop goroutine
	pn.UnsubscribeAll()
	close(done)

	// snippet.hide
	// Small delay to ensure cleanup completes before next example
	time.Sleep(100 * time.Millisecond)
	// snippet.show

	// Output:
	// Subscribed to wildcard channels
}
```

:::note Wildcard grants and revokes
Only one level (`a.*`) of wildcarding is supported. If you grant on `*` or `a.b.*`, the grant will treat `*` or `a.b.*` as a single channel named either `*` or `a.b.*`. You can also revoke permissions from multiple channels using wildcards but only if you previously granted permissions using the same wildcards. Wildcard revokes, similarly to grants, only work one level deep, like `a.*`.
:::

#### Subscribing with state

:::warning Requires Presence
This method requires that the Presence add-on is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/). For information on how to receive presence events and what those events are, refer to [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events#subscribe-to-presence-channel).
:::

:::note Required UUID
Always set the `UUID` to uniquely identify the user or device that connects to PubNub. This `UUID` should be persisted, and should remain unchanged for the lifetime of the user or the device. If you don't set the `UUID`, you won't be able to connect to PubNub.
:::

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_subscribeWithState demonstrates subscribing with state
func Example_subscribeWithState() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	listener := pubnub.NewListener()
	done := make(chan bool)

	go func() {
		for {
			select {
			case status := <-listener.Status:
				switch status.Category {
				case pubnub.PNConnectedCategory:
					// Set state after connection is established
					response, status, err := pn.SetState().
						Channels([]string{"ch"}).
						State(map[string]interface{}{
							"field_a": "cool",
							"field_b": 21,
						}).Execute()

					if err != nil {
						fmt.Printf("Error: %v\n", err)
					}

					if response != nil && status.StatusCode == 200 {
						fmt.Println("State set successfully")
					}
					done <- true
				}
			case <-listener.Message:
				// Handle messages
			case <-listener.Presence:
				// Handle presence
			case <-done:
				return
			}
		}
	}()

	pn.AddListener(listener)

	pn.Subscribe().
		Channels([]string{"ch"}).
		Execute()

	<-done

	pn.UnsubscribeAll()

	// snippet.hide
	// Small delay to ensure cleanup completes before next example
	time.Sleep(100 * time.Millisecond)
	// snippet.show

	// Output:
	// State set successfully
}
```

#### Subscribe to a channel group

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"

	pubnub "github.com/pubnub/go/v9"
)

// Example_subscribeToChannelsAndGroups demonstrates subscribing to both individual channels and channel groups
func Example_subscribeToChannelsAndGroups() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	defer pn.DeleteChannelGroup().ChannelGroup("my-group").Execute()
	// snippet.show

	// Create a channel group
	pn.AddChannelToChannelGroup().
		Channels([]string{"group-channel-1", "group-channel-2"}).
		ChannelGroup("my-group").
		Execute()

	listener := pubnub.NewListener()

	// Create a done channel to stop the goroutine when needed
	done := make(chan bool)

	go func() {
		for {
			select {
			case <-listener.Status:
				// Handle connection status changes

			case message := <-listener.Message:
				// Messages from both individual channels and channel group channels
				fmt.Printf("Message from %s: %v\n",
					message.Channel, message.Message)

			case <-done:
				// Stop the goroutine when done signal is received
				return
			}
		}
	}()

	pn.AddListener(listener)

	// Subscribe to individual channels AND channel groups simultaneously
	pn.Subscribe().
		Channels([]string{"standalone-channel-1", "standalone-channel-2"}).
		ChannelGroups([]string{"my-group"}).
		Execute()

	fmt.Println("Subscribed to channels and groups")

	// When done, unsubscribe and stop goroutine
	pn.UnsubscribeAll()
	close(done)

	// Output:
	// Subscribed to channels and groups
}
```

#### Subscribe to the Presence channel of a channel group

:::note Requires Stream Controller and Presence add-ons
This method requires both the *Stream Controller* and *Presence* add-ons are enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// subscribeToChannelGroupPresence demonstrates subscribing to presence of channel groups
func subscribeToChannelGroupPresence() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"

	pn := pubnub.NewPubNub(config)

	// Subscribe to channel groups with presence
	pn.Subscribe().
		ChannelGroups([]string{"cg1", "cg2"}). // subscribe to channel groups
		Timetoken(int64(1337)).                // optional, pass a timetoken
		WithPresence(true).                    // also subscribe to related presence information
		Execute()
}
```

## Unsubscribe

When subscribed to a single channel, this function causes the client to issue a `leave` from the `channel` and close any open socket to the PubNub Network. For multiplexed channels, the specified `channel`(s) will be removed and the socket remains open until there are no more channels remaining in the list.

:::warning Unsubscribing from all channels
**Unsubscribing** from all channels, and then **subscribing** to a new channel Y is not the same as subscribing to channel Y and then unsubscribing from the previously-subscribed channel(s). Unsubscribing from all channels resets the last-received `timetoken` and thus, there could be some gaps in the subscription that may lead to message loss.
:::

### Method(s)

To `Unsubscribe from a channel` you can use the following method(s) in the Go SDK:

```go
pn.Unsubscribe().
    Channels([]string).
    ChannelGroups([]string).
    QueryParam(queryParam).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Channels`Type: []stringDefault: `false` | Unsubscribe to channels, Either `channel` ID or `channelGroup` is required. |
| `ChannelGroups`Type: []stringDefault: `false` | Unsubscribe to channel groups, Either `channel` ID or `channelGroup` is required. |
| `QueryParam`Type: map[string]stringDefault: `nil` | QueryParam accepts a map, the keys and values of the map are passed as the query string parameters of the URL called by the API. |

### Sample code

Unsubscribe from a channel:

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_unsubscribe demonstrates unsubscribing from channels
func Example_unsubscribe() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// First subscribe to a channel
	pn.Subscribe().
		Channels([]string{"my-channel"}).
		Execute()

	// Unsubscribe from specific channel(s)
	pn.Unsubscribe().
		Channels([]string{"my-channel"}).
		Execute()

	fmt.Println("Unsubscribed from channel")

	// Output:
	// Unsubscribed from channel
}
```

:::note Event listeners
The response of the subscription is handled by Listener. Please see the [Listeners section](https://www.pubnub.com/docs/sdks/go/api-reference/configuration#event-listeners) for more details.
:::

### Rest response from server

The output below demonstrates the response to a successful call:

```javascript
if presence.Event == "leave" {
    presence.UUID // left-uuid
    presence.Timestamp // 1345546797
    presence.Occupancy // 2
}
```

### Other examples

#### Unsubscribing from multiple channels

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_unsubscribeMultiple demonstrates unsubscribing from multiple channels
func Example_unsubscribeMultiple() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// First subscribe to multiple channels
	pn.Subscribe().
		Channels([]string{"my-channel", "my-channel2"}).
		Execute()

	// Unsubscribe from multiple channels
	pn.Unsubscribe().
		Channels([]string{"my-channel", "my-channel2"}).
		Execute()

	fmt.Println("Unsubscribed from multiple channels")

	// Output:
	// Unsubscribed from multiple channels
}
```

##### Example response

```json
if presence.Event == "leave" {
    presence.UUID // left-uuid
    presence.Timestamp // 1345546797
    presence.Occupancy // 2
}
```

#### Unsubscribe from a channel group

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"

	pubnub "github.com/pubnub/go/v9"
)

// Example_unsubscribeFromChannelGroup demonstrates unsubscribing from a channel group
func Example_unsubscribeFromChannelGroup() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	defer pn.DeleteChannelGroup().ChannelGroup("my-group").Execute()
	// snippet.show

	// First, add channels to the group and subscribe
	pn.AddChannelToChannelGroup().
		Channels([]string{"channel-1", "channel-2"}).
		ChannelGroup("my-group").
		Execute()

	pn.Subscribe().
		ChannelGroups([]string{"my-group"}).
		Execute()

	// Unsubscribe from the channel group
	pn.Unsubscribe().
		ChannelGroups([]string{"my-group"}).
		Execute()

	fmt.Println("Unsubscribed from channel group")

	// Output:
	// Unsubscribed from channel group
}
```

## Unsubscribe all

Unsubscribe from all channels and all channel groups

### Method(s)

```go
UnsubscribeAll()
```

### Sample code

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v9"
)

// Example_unsubscribeAll demonstrates unsubscribing from all channels
func Example_unsubscribeAll() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Subscribe to multiple channels
	pn.Subscribe().
		Channels([]string{"channel-1", "channel-2", "channel-3"}).
		Execute()

	// Unsubscribe from all channels at once
	pn.UnsubscribeAll()

	fmt.Println("Unsubscribed from all channels")

	// snippet.hide
	// Small delay to ensure cleanup completes before next example
	time.Sleep(100 * time.Millisecond)
	// snippet.show

	// Output:
	// Unsubscribed from all channels
}
```

### Returns

None

## Terms in this document

* **Channel** - A pathway for sending and receiving messages between devices, created automatically when you first use it, that can handle any number of users and messages for different communication needs, like 1-1 text chats, group conversations, and other data streaming.
* **Channel pattern** - A way to group and analyze channel data to track performance metrics like message counts and user engagement over time with PubNub Insights.
* **Signal** - A non-persistent message limited to 64 bytes designed for high-volume usecases where the the most recent data is relevant, like GPS location updates.