package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
// 官方地址:https://godoc.org/github.com/gomodule/redigo/redis#pkg-examples
/***************************** redis連接 *********************************/
// option := redis.DialPassword("123456") 如果redis有密碼,放在第三個選項
c, err := redis.Dial("tcp", "127.0.0.1:6379")
if err != nil {
fmt.Println(err)
return
}
defer c.Close()
/***************************** Do方法 *************************************/
// 執行redis語句的通用方法
// 可執行的命令參考 :https://redis.io/commands
// set name card 成功返回ok
res,err := c.Do("SET", "NAME", "card")
if err != nil {
fmt.Println(err)
}
fmt.Println(res)
// get name 成功返回interface{}
res, err = c.Do("GET", "NAME")
if err != nil {
fmt.Println(err)
}
// 進行類型斷言
switch t := res.(type) {
case []byte:
fmt.Println(string(t))
}
/***************************** 管道 *************************************/
// redigo支持管道操作Send(),Flush(),Receive()
// Send() 發送命令到輸出緩沖區。
// Send(commandName string, args ...interface{}) error
// Flush() 寫入命令並刷新輸出緩沖區。
// Flush() error
// Receive()接收服務器的返回值
// Receive() (reply interface{}, err error)
c.Send("SET", "foo", "bar") // 設置語句到緩沖區
c.Send("GET", "foo") // 設置語句到緩沖區
c.Flush() // 發送語句
res,_ =c.Receive() // 接收第一個Send()的返回值
fmt.Println(res)
res,_ = c.Receive() // 接收第二個Send()的返回值
fmt.Println(res)
// Do方法結合了Send,Flush和Receive方法的功能。
// Do方法首先寫入命令並刷新輸出緩沖區。
// 接下來,Do方法接收所有待處理的回復,包括Do執行的命令的回復。
// 如果收到的任何回復都是錯誤,則Do返回錯誤。 如果沒有錯誤,則Do返回最后一個返回值。
// 如果Do方法的命令參數是“”,則Do方法將刷新輸出緩沖區並接收掛起的回復而不發送命令。
// MULTI類似於事務的begin commit事務處理
c.Send("MULTI")
c.Send("INCR", "money")
c.Send("INCR", "count")
r, err := c.Do("EXEC")
fmt.Println(r) // [1,1]
/***************************** 並發 *************************************/
// redigo支持一個並發調用Receive()方法和一個並發調用Send()和Flush()方法
// 不支持其他並發,包括對Do方法的並發調用
// 如果需要完全並發訪問redis,需要使用線程安全池goroutine中獲取,使用和釋放連接。
// 從線程中返回具有前一段時間描述的並發限制
// 關於redis連接池會單獨寫一個
/***************************** 發布和訂閱 *******************************/
// 擴展:SUBSCRIBE、UNSUBSCRIBE和PUBLISH 三個命令實現了發布與訂閱信息泛型.
// 在這個實現中, 發送者(發送信息的客戶端)不是將信息直接發送給特定的接收者(接收信息的客戶端),
// 而是將信息發送給頻道(channel), 然后由頻道將信息轉發給所有對這個頻道感興趣的訂閱者。
// 也就是說發送者無須知道任何關於訂閱者的信息, 而訂閱者也無須知道是那個客戶端給它發送信息,
// 它只要關注自己感興趣的頻道即可
// 對發布者和訂閱者進行解構(decoupling),可以極大地提高系統的擴展性(scalability),
// 並得到一個更動態的網絡拓撲(network topology)。
// redis可以訂閱任意數量的頻道。
// 通過使用Send(),Flush(),和Receive()方法實現 Pub / Sub訂閱者。
// 訂閱者
// c.Send("SUBSCRIBE", "example")
// c.Flush()
// for {
// reply, err := c.Receive()
// if err != nil{
// fmt.Println(err)
// }
// // 處理接收到的信息
// fmt.Println(reply)
// }
// PubSubConn類型使用便捷方法包裝Conn以實現訂閱者。
// Subscribe,PSubscribe,Unsubscribe和PUnsubscribe方法發送和刷新訂閱管理命令。
// receive方法將推送的消息轉換為方便的類型,以便在switch中使用。
// psc := redis.PubSubConn{Conn:c}
// psc.Subscribe("example")
// for {
// switch v := psc.Receive().(type) {
// case redis.Message:
// fmt.Printf("%s: message: %s \n", v.Channel, v.Data)
// case redis.Subscription:
// fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
// case error:
// fmt.Println(v)
// }
// }
/***************************** 返回值助手函數 *******************************/
// Bool,Int,Bytes,String,Strings和Values函數將返回值轉換為特定類型的值。
// 為了方便地包含對連接Do和Receive方法的調用,這些函數采用了類型error的第二個參數。
// 如果錯誤是非nil,則輔助函數返回錯誤。 如果錯誤為nil,則該函數將回復轉換為指定的類型
exists, err := redis.Bool(c.Do("EXISTS", "foo"))
if err != nil {
// handle error return from c.Do or type conversion error.
}
fmt.Println(exists)
}