# 7. string

# 7.1 底层

  • runtime/string.go

    type stringStruct struct {
    	str unsafe.Pointer		// 指向底层 Byte 数组
    	len int								// String 所占字节数
    }
    
  • reflect/value.go

    type StringHeader struct {
    	Data uintptr
    	Len  int
    }
    

# 7.2 测试

	s_en := "hedonwang"
	s_cn := "王小佳"

	fmt.Println(unsafe.Sizeof(s_en)) //16
	fmt.Println(unsafe.Sizeof(s_cn)) //16
	s_en_sh := (*reflect.StringHeader)(unsafe.Pointer(&s_en))		//16
	s_cn_sh := (*reflect.StringHeader)(unsafe.Pointer(&s_cn))		//16

	fmt.Println(s_en_sh.Len)	//9
	fmt.Println(s_cn_sh.Len)	//9

Unicode & UTF-8

Go 统一使用 UTF-8 编码。

  • Unicode 是一种统一的字符集,囊括了 159 种文字的 144679 个字符,14w 个字符至少需要 3 个字节表示,英文字母均排在前 128 个。
  • Unicode 每个字符都用 3 个字节来表示,如果字符排在前面,就造成了很多的浪费,于是就出现变长编码 UTF-8:
    • 128 个 US-ASCII 字符只需要 1 个字节编码
    • 西方常用字符需要 2 个字节编码
    • 其他字符需要 3 个字节编码,极少数需要 4 个字节编码

# 7.3 访问

  • fori 去访问 str[i] 访问的是 byte[] 字节数组

    str := "王小佳hedonwang"
    for i := 0; i < len(str); i++ {
      fmt.Printf("%v ", str[i])
    }
    // 231 142 139 229 176 143 228 189 179 104 101 100 111 110 119 97 110 103
    
  • 访问字符需要用 for ... range,即访问 rune[] 数组

    str := "王小佳hedonwang"
    for _, char := range str {
      fmt.Printf("%c ", char)
    }
    // 王 小 佳 h e d o n w a n g
    

# 7.4 切分

  • 先转为 rune[] 切片,再进行切片切分

    s := string([]rune(s)[:3])
    
上次更新: 8/13/2022, 11:21:24 AM