• golang——字符串与编码


    1、字符编码

    (1)ASCII码

    一个字节表示的英文、数字、标点符号等字符。

    国际标准ASCII码为0-127即128个字符,二进制最高位为0,其余为扩展ASCII码。

    (2)GB2312

    两字节,主要包含简体的常用中文及符号的字符集编码。

    (3)GBK

    单双字节变长编码,主要包含简体繁体中文和一些符号、偏旁部首的字符集编码。

    (4)GB18030

    GBK编码无法满足需求扩展,多出来的部分使用四字节编码,即单、双、四字节编码;

    扩展了汉字,还包括了少数民族文字;

    (5)Unicode

    因各国语言、字符差异,Unicode将所有字符统一为一套字符集。

    UTF-8、UTF-16、UTF-32是对Unicode字符集的不同编码方案。

    (6)UTF-8

    变长编码方式,1-4字节表示一个字符,可节省存储空间;

    英文1字节,中文一般3字节,最多4字节;

    编码规则:

    》单字节:同标准ASCII码,最高位为0,0-127表示128个字符

    》多字节:n字节,高位到低位,第一字节前n位为1,第n+1位为0;后面字节前两位为10;剩余位由低位向高位填补Unicode吗,多出补0;

    110XXXXX 10XXXXXX

    1110XXXX 10XXXXXX 10XXXXXX

    2、字符串遍历

    golang使用utf-8的编码方式

    2.1、for循环遍历字符串

    func main() {
    	str := "test笃志弘毅"
    	for i := 0; i < len(str); i++ {
    		fmt.Printf("%v %c,", str[i], str[i])
    	}
    }
    //116 t,101 e,115 s,116 t,231 ç,172 ¬,131 ƒ,229 å,191 ¿,151 —,229 å,188 ¼,152 ˜,230 æ,175 ¯,133 …,
    

      以下标访问字符串时,按单字节(byte)访问,超出单字节的编码会出现乱码。

    2.2、for range遍历字符串

    func main() {
    	str := "test笃志弘毅"
    	for i, v := range str {
    		fmt.Printf("%d-%c-%v ", i, v, v)
    	}
    }
    //0-t-116 1-e-101 2-s-115 3-t-116 4-笃-31491 7-志-24535 10-弘-24344 13-毅-27589
    

      for range遍历字符串时,按字符(rune)访问,中文正常显示

    3、字符串转字符切片字节切片的差异

    func main() {
    	str := "test笃志弘毅"
    	runeS := []rune(str)
    	for i := 0; i < len(runeS); i++ {
    		fmt.Printf("%c-%v ", runeS[i], runeS[i])
    	}
    	fmt.Println()
    	byteS := []byte(str)
    	for i := 0; i < len(byteS); i++ {
    		fmt.Printf("%c-%v ", byteS[i], byteS[i])
    	}
    }
    //t-116 e-101 s-115 t-116 笃-31491 志-24535 弘-24344 毅-27589 
    //t-116 e-101 s-115 t-116 ç-231 ¬-172 ƒ-131 å-229 ¿-191 —-151 å-229 ¼-188 ˜-152 æ-230 ¯-175 …-133
    

    4、字符串注意点

    (1)字符串的零值为空串"",不是nil

    func main() {
    	var str string
    	fmt.Println(str == "") //true
    	//fmt.Println(str == nil)
    	//invalid operation: str == nil (mismatched types string and nil)
    	//无效操作(string和nil类型不匹配)
    }
    

    (2)索引访问或是切片得到的都是按字节处理,可能出现乱码

    (3)len函数返回的是字节数,而不是字符数  

    func main() {
    	str := "test笃志弘毅"
    	fmt.Println(len(str))//16
    }
    

    (4)不能通过索引或指针修改字符串字符

    func main() {
    	str := "test笃志弘毅"
    	str[2] = 'a'     //cannot assign to str[2]
    	*(&str[2]) = 'b' // cannot take the address of str[2]
    	fmt.Println(str)
    }
    

    (5)字符串的切片操作返回的是字符串,而不是切片

    func main() {
    	str := "test笃志弘毅"
    	str1 := str[:]
    	str2 := str[:]
    	fmt.Printf("%T %p %p
    ", str1, &str1, &str2)
    }
    //string 0xc0000581c0 0xc0000581d0
    
    笃志:“博学而笃志,切问而近思,仁在其中矣。”
    弘毅:“士不可以不弘毅,任重而道远。”
    止于至善:“大学之道,在明明德,在亲民,在止于至善。”
    关注:笃志弘毅,止于至善
  • 相关阅读:
    C#中的Dictionary的使用
    关于加密和解密的方法
    单链表逆置
    稀疏矩阵存储
    数组内存地址
    堆和栈的区别
    vc++6.0快捷键
    springMvc-02
    SpringMvc-01
    数据库字段设置问题,具体问题具体分析
  • 原文地址:https://www.cnblogs.com/dzhy/p/10936926.html
Copyright © 2020-2023  润新知