学习《GO语言学习笔记》的学习笔记之5.1 数据之字符串 (详解)

Source
版权声明:诸葛老刘所有 https://blog.csdn.net/weixin_39791387/article/details/88134157

本文适合初学者阅读

  • 5.1 字符串
  • 字符串是不可变字节序列, 其本身是一个复合结构.
  • 头部指针指向字节数组,但没有NULL结尾
  • 字符串默认是"", 不是nil
  • 使用"`"(tab键上面那个键)定义不做转义处理的原始字符串,支持跨行.
package main


func main() {
	s := `test\r\n,
	line2`

	println(s)
}

结果输出:

test\r\n,
	line2
  • 支持"!=, ==, >, <, +, +="操作符.
package main

func main() {
	s := "ab" +     // 跨行时, 加法操作符必须在上一行结尾
		"cd"

	println(s == "abcd")   	// true
	println(s > "abc")    	// true
}
  • 允许以索引号访问字节数组(非字符), 但不能获取元素地址.
func main() {
	s := "abc"
	println(s[1])    // a
	println(&s[1])   // 错误: cannot take the address of s[1]
}
  • 以切片语法(就是python里切片)返回字符串时, 其内部依旧指向原字节数据.
  • 使用for 遍历字符串时, 分byte和rune两种方式
package main

import (
	"fmt"
)

func main() {
	s := "abced"

	for i := 0; i < len(s); i++ {
		fmt.Printf("%d: %c\n", i, s[i])     // byte
	}

	for index, element := range s {     // rune:返回数组索引号, 及unicode字符
		fmt.Printf("%d: %c\n", index, element)
	}
}
  • 转换
    • 要修改字符串, 须将其转换为可变类型([]rune或[]byte),待完成后再转换回来.但不管如何转换,都须重新分配内存,并复制数据.
  • 性能
    • 用加法操作符拼接字符串时,每次都须重新分配内存, 在构建"超大"字符串时,性能就会很差
    • 改进思路是预分配足够的内存空间.常用方法是用strings.Join()函数, 它会统计所有参数的长度, 并一次性完成内存分配操作.
    • 或者使用bytes.Buffer也能完成类似操作,且性能相当.
    • 对于数量较少的字符串格式化拼接,可使用fmt.Sprintf() 或者 text/template等方法.
  • Unicode
    • 类型rune专门用来存储Unicode码点, 它是int32的别名,使用单引号的字面量,其默认类型就是rune
package main

import (
	"fmt"
)

func main() {
	s := '我'    // rune类型的

	x := string(s)   // rune to string
	y := byte(s)    // rune to byte

	s2 := string(y)    // byte to string
	r2 := rune(y)       // byte to rune

	fmt.Println(x, y, s2, r2)
}
// 我 17  17
  • 标准库unicode里提供了丰富的操作函数. 除验证函数外, 还可用RuneCountInString代替len返回准确的Unicode字符数量.
package main

import "unicode/utf8"

func main() {
	println(len("hello"), utf8.RuneCountInString("hello"))  // 5 5
	println(len("世界"), utf8.RuneCountInString("世界"))    // 6 2
}