• 在 Go 语言中处理 Unicode


    如果‘Go’通常是指在公园散步,用Go语言处理Unicode码可以描述为不小心走进了雷区,比如,如果我们要获取从前端页面的一句简单字符串“Hello,世界”的长度.会得到什么结果?

    1 fmt.Println(len("Hello, 世界"))
    2  >>> 13
    等下,刚才发生了什么?长度难道不该是9么?其他额外的4个字符是从哪来的?在编译中,Go 实际上把字符串编码为一个byte.go不像Python2.x一样让你区分普通ASCII码并反编码处理字符串,所以go还是不能从将中文字符编码为 byte的实现中抽离出来,因为中文字符在ASCII表示中占用3byte而普通字符只占用1byte,所以Go告诉你长度是 1*7+3*2=13.这对于那些想测试他们的ASCII字符串长度的人将是个令人迷惑的大水坑!看下面的例子
    1 hello := "Hello, 世界" for i := range hello {
    2     fmt.Print(string(hello[i]))
    3 }
    4 >>> Hello, äç
    出问题了,好吧,‘世界’怎么变成了‘ äç’?也许我已经能听到你的咆哮了。。但是当你使用第二种range处理字符串,你确实可以这样处理
    1 hello := "Hello, 世界" for _, c := range hello {
    2     fmt.Print(string(c))
    3 }
    4 >>> Hello, 世界
    BigOwen
    BigOwen
    翻译于 昨天(10:25)

    0人顶

     翻译的不错哦!

    结果好了很多! 但我们确实不能这样做,为什么? 用一个小例子, 假设我们只是想用字符串中的每个字符与下个字符比较是否一样的. 简单的处理方式可能是这样:
    1 func CompareChars(word string) { for i, c := range word { if i < len(word)-1 {
    2             fmt.Print(string(word[i+1]) == string(c), ",")
    3         }
    4     }
    5 }
    6 ...
    7 CompareChars("hello")
    8 >>> false,false,true,false,

    可是使用ASCII的字符串作为入参,结果实在是太烂了!如果我们使用中文说你好的话情况会是这样:

    1 CompareChars("你好好好")
    2 >>> false,false,false,false,

    很明显这些字符串永远不会相等,因为我们总是用‘好’和好的第一byte的ASCII码‘\xE5’比较。

    那么该怎么办?如果我们探索的够深,就会发现go排除了unicode/utf8的引用包,这个包不提供特别多功能,但是却能是我们解决遇到的第一个问题,查询‘hello’字符串的长度:

    1 import ( "fmt" "unicode/utf8" ) ... fmt.Println(utf8.RuneCountInString("Hello, 世界"))
    2 >>> 9
    BigOwen
    BigOwen
    翻译于 昨天(11:17)

    0人顶

     翻译的不错哦!

    好了,我们一开始期望的长度出现了。现在来升级一下我们先用到的CompareChars 函数,使它能比较Unicode编码。

    1 func CompareChars(word string) { s := []byte(word) for utf8.RuneCount(s) > 1 { r, size := utf8.DecodeRune(s) s = s[size:] nextR, size := utf8.DecodeRune(s) fmt.Print(r == nextR, ",") } }
    2 ... CompareChars("hello")
    3 >>> false,false,true,false, CompareChars("你好好好")
    4 >>> false,true,true,
    起作用了!

    这个故事的寓意:工作时要非常小心,尤其是当与循环中的Unicode遍历字符串。最重要的是,在适当的情况下,使用内置的UTF-8封装,并牢记写测试要包含Unicode和ASCII字符串,。

  • 相关阅读:
    【转】c++继承中的内存布局
    Google 开源项目风格指南
    常见面试题
    PHP7.1中使用openssl替换mcrypt
    phpunit实践笔记
    PHP的错误处理
    CI的扩展机制
    #CI的MVC实现
    Laravel中的队列处理
    laravel的模块化是如何实现的
  • 原文地址:https://www.cnblogs.com/shihao/p/3098426.html
Copyright © 2020-2023  润新知