最近在学习Go 语言时,遇到一个很有意思的问题,记录一下。

第一次应用redisgo 时,有点懵,怎么取出来的数据跟我存的齐全不一样?

package mainimport (    "fmt"    "github.com/gomodule/redigo/redis")func main() {  conn, _ := redis.Dial("tcp", "127.0.0.1:6379")  defer conn.Close()    conn.Send("SET", "hello", "hello")  conn.Send("GET", "hello")  conn.Flush()    v, _ := conn.Receive()  fmt.Println(v)}

打印后果:

[104 101 108 108 111]

当看到这个打印后果时,咦~我明明存进去的是一个 hello,怎么取出来却成了一个数组?

要答复这个问题,就得理解Go 语言中的字符串这个数据结构了。

意识字符串

字符串是Go 语言中最罕用的根底数据类型之一,尽管字符串往往是被看作是一个整体,但实际上字符串是一块间断的内存空间,也能够了解成是一个由字符组成的数组。

字符串尽管在 Go 语言中是根本类型 string(hello),然而它其实就是字符组成的数组([104 101 108 108 111])。

作为数组来说,它会占用一片间断的内存空间,这片间断的内存空间就存储了一些字节,这些字节独特组成了字符串。

Go 语言中的字符串是一个只读的字节数组切片

尝试将数组切片转换成字符串:

package mainimport "fmt"func main()  {  // 留神这里的数据类型是 uint8,而不是 int、uint    sli := []uint8{104, 101, 108, 108, 111}    fmt.Println(sli)    fmt.Printf("%T \n", sli)        fmt.Println(string(sli))           fmt.Printf("%T \n", string(sli))}

打印后果:

[104 101 108 108 111][]uint8 hellostring 

来看看hello这个字符串在内存中的存储形式:

你可能会问:0x680x650x6c0x6c0x6f这些货色是什么?

他们是hello 这个字符串的切片数组的每一个数字所对应的十六进制:

  • 104 => 0x68
  • 101 => 0x65
  • 108 => 0x6c
  • 108 => 0x6c
  • 111 => 0x6f

申明字符串

在Go 语言中,有两种字面量形式能够申明一个字符串,一种是应用双引号,另一种则是应用反引号:

str1 := "this is a string"str2 := `this is another`

应用双引号申明的字符串其实和其余语言中的字符串申明没有太多区别,它只能用于简略、单行的字符串。

并且如果字符串外部呈现双引号时须要应用 \ 符号来防止编译器解析谬误,而应用反引号则能够很好的解脱这一限度。

在遇到须要写 JSON 或者其余数据格式的场景下十分不便,上面两个 JSON 字符串的写法都没问题,但显然第二种形式更简洁、天然、便于浏览。

str1 := "{\"page\": 1, \"fruits\": [\"apple\", \"pear\"]}"str2 := `{"page": 1, "fruits": ["apple", "pear"]}`

参考链接

  • 谈 Golang 中的字符串和字节数组