unicode介绍

Unicode只是定义了一个字符和一个编码的映射,但是呢,对应的存储却没有制定。 比如一个编码0x0041代表大写字母A,那么可能有一种存储至少有4个字节,那可能0x00000041来存储代表A。 这个就是unicode的具体实现。unicode的具体实现有很多种,UTF-8和UTF-16就是其中两种。

UTF-8表示最少用一个字节就能表示一个字符的编码实现。它采取的方式是对不同的语言使用不同的方法,将unicode编码按照这个方法进行转换。 我们只要记住最后的结果是英文占一个字节,中文占三个字节。这种编码实现方式也是现在应用最为广泛的方式了。
UTF-16表示最少用两个字节能表示一个字符的编码实现。同样是对unicode编码进行转换,它的结果是英文占用两个字节,中文占用两个或者四个字节。 实际上,UTF-16就是最严格实现了unicode4.0。但由于英文是最通用的语言,所以推广程度没有UTF-8那么普及。

Go对unicode的支持

回到go对unicode包的支持,由于UTF-8的作者Ken Thompson同时也是go语言的创始人,所以说,在字符支持方面,几乎没有语言的理解会高于go了。 go对unicode的支持包含三个包:

unicode
unicode/utf8
unicode/utf16

unicode包包含基本的 字符判断函数。utf8包主要 负责rune和byte之间的转换。utf16包负责 rune和uint16数组之间的转换。

由于字符的概念有的时候比较模糊,比如字符(小写a)普通显示为a,在重音字符中(grave-accented)中显示为à。 这时候字符(character)的概念就有点不准确了, 因为a和à显然是两个不同的unicode编码,但是却代表同一个字符,所以引入了rune。 一个rune就代表一个unicode编码,所以上面的a和à是两个不同的rune

这里有个要注意的事情,go语言的所有代码都是UTF8的,所以如果我们在程序中的字符串都是utf8编码的,但是我们的单个字符(单引号扩起来的)却是unicode的。  (提出问题:如何提取字符串中的中文?)

Unicode包详解

const (MaxRune         = '\U0010FFFF' // Unicode 码点的最大值ReplacementChar = '\uFFFD'     // 表示无效的码点MaxASCII        = '\u007F'     // 最大 ASCII 值MaxLatin1       = '\u00FF'     // 最大 Latin-1 值
)

unicode包中定义好多变量,这些变量都是*RangeTable类型的。定义三组变量字典类型:Categories is the set of Unicode category tables. Properties is the set of Unicode property tables. Scripts is the set of Unicode script tables. map[string]*RangeTable    key值是string类型的, value是*RangeTable类型的。

// RangeTable 定义一个 Unicode 码点集合,包含 16 位和 32 位两个范围列表。
// 这两个列表必须经过排序而且不能重叠。R32 中只能包含大于 16 位的值。
type RangeTable struct {R16         []Range16R32         []Range32LatinOffset int // R16 中 Hi <= MaxLatin1 的条目数。
}// Range16 表示一个 16 位的 Unicode 码点范围。范围从 Lo 到 Hi,具有指定的步长。
type Range16 struct {Lo     uint16Hi     uint16Stride uint16 // 步长
}// Range32 表示一个 32 位的 Unicode 码点范围。范围从 Lo 到 Hi,具有指定的步长。
// Lo 和 Hi 必须都大于 16 位。
type Range32 struct {Lo     uint32Hi     uint32Stride uint32 // 步长
}
// 判断字符 r 是否在 rangtab 范围内。
// 可用的 RangeTable 参见 go/src/unicode/tables.go。  通过 一系列变量的字典对象可获得。
func Is(rangeTab *RangeTable, r rune) bool
//判断 是否字符r是否在 可变参数*RangeTable范围内
func In(r rune, ranges ...*RangeTable) bool

程序示例:

// 示例:判断汉字
func main() {for _, r := range "Hello 世界!" {// 判断字符是否为汉字if unicode.Is(unicode.Scripts["Han"], r) {  //或者In都是可以的fmt.Printf("%c", r) // 世界}}
}// 更多 unicode.Scripts 取值请参考:http://www.cnblogs.com/golove/p/3269099.html   变量的定义
func IsLower(r rune) bool   //判断字符r是否为小写格式
// 判断字符 r 是否为 Unicode 规定的 Title 字符
// 大部分字符的 Title 格式就是其大写格式
// 只有少数字符的 Title 格式是特殊字符
// 这里判断的就是特殊字符
func IsTitle(r rune) bool
func IsUpper(r rune) bool   //判断字符r是否是大写格式// To 将字符 r 转换为指定的格式
// _case 取值:UpperCase、LowerCase、TitleCase
func To(_case int, r rune) rune
func ToLower(r rune) rune
func ToTitle(r rune) rune
func ToUpper(r rune) rune

程序示例:

// 示例:判断大小写
func main() {for _, r := range "Hello ABC!" {// 判断字符是否为大写if unicode.IsUpper(r) {fmt.Printf("%c", r) // HABC}}for _, r := range "Hello abc!" {// 判断字符是否为小写if unicode.IsLower(r) {fmt.Printf("%c", r) // elloabc}}for _, r := range "Hello ᾏᾟᾯ!" {// 判断字符是否为标题if unicode.IsTitle(r) {fmt.Printf("%c", r) // ᾏᾟᾯ}}
}
// 示例:输出 Unicode 规定的标题字符
func main() {for _, cr := range unicode.Lt.R16 {for i := cr.Lo; i <= cr.Hi; i += cr.Stride {fmt.Printf("%c", i)}} // DžLjNjDzᾈᾉᾊᾋᾌᾍᾎᾏᾘᾙᾚᾛᾜᾝᾞᾟᾨᾩᾪᾫᾬᾭᾮᾯᾼῌῼ
}
// 示例:转换大小写
func main() {s := "Hello 世界!"for _, r := range s {fmt.Printf("%c", unicode.ToUpper(r))} // HELLO 世界!for _, r := range s {fmt.Printf("%c", unicode.ToLower(r))} // hello 世界!for _, r := range s {fmt.Printf("%c", unicode.ToTitle(r))} // HELLO 世界!for _, r := range s {fmt.Printf("%c", unicode.To(unicode.UpperCase, r))} // HELLO 世界!for _, r := range s {fmt.Printf("%c", unicode.To(unicode.LowerCase, r))} // hello 世界!for _, r := range s {fmt.Printf("%c", unicode.To(unicode.TitleCase, r))} // HELLO 世界!
}
// IsDigit 判断 r 是否为一个十进制的数字字符
func IsDigit(r rune) bool// IsNumber 判断 r 是否为一个数字字符 (类别 N)
func IsNumber(r rune) bool// IsLetter 判断 r 是否为一个字母字符 (类别 L)
// 汉字也是一个字母字符
func IsLetter(r rune) bool// IsSpace 判断 r 是否为一个空白字符
// 在 Latin-1 字符集中,空白字符为:\t, \n, \v, \f, \r,
// 空格, U+0085 (NEL), U+00A0 (NBSP)
// 其它空白字符的定义有“类别 Z”和“Pattern_White_Space 属性”
func IsSpace(r rune) bool// IsControl 判断 r 是否为一个控制字符
// Unicode 类别 C 包含更多字符,比如代理字符
// 使用 Is(C, r) 来测试它们
func IsControl(r rune) bool// IsGraphic 判断字符 r 是否为一个“图形字符”
// “图形字符”包括字母、标记、数字、标点、符号、空格
// 他们分别对应于 L、M、N、P、S、Zs 类别
// 这些类别是 RangeTable 类型,存储了相应类别的字符范围
func IsGraphic(r rune) bool// IsPrint 判断字符 r 是否为 Go 所定义的“可打印字符”
// “可打印字符”包括字母、标记、数字、标点、符号和 ASCII 空格
// 他们分别对应于 L, M, N, P, S 类别和 ASCII 空格
// “可打印字符”和“图形字符”基本是相同的,不同之处在于
// “可打印字符”只包含 Zs 类别中的 ASCII 空格(U+0020)
func IsPrint(r rune) bool// IsPunct 判断 r 是否为一个标点字符 (类别 P)
func IsPunct(r rune) bool// IsSymbol 判断 r 是否为一个符号字符
func IsSymbol(r rune) bool// IsMark 判断 r 是否为一个 mark 字符 (类别 M)
func IsMark(r rune) bool// IsOneOf 判断 r 是否在 set 范围内
func IsOneOf(set []*RangeTable, r rune) bool
// 示例:判断汉字和标点
func main() {// 将 set 设置为“汉字、标点符号”set := []*unicode.RangeTable{unicode.Han, unicode.P}  //指针切片for _, r := range "Hello 世界!" {if unicode.IsOneOf(set, r) {fmt.Printf("%c", r)}} // 世界!
}
// 示例:输出所有 mark 字符
func main() {for _, cr := range unicode.M.R16 {Lo, Hi, Stride := rune(cr.Lo), rune(cr.Hi), rune(cr.Stride)for i := Lo; i >= Lo && i <= Hi; i += Stride {if unicode.IsMark(i) {fmt.Printf("%c", i)}}}
}
// SimpleFold 在 Unicode 字符表中从字符 r 开始环绕查找(到尾部后再从头开始)
// 下一个与 r 大小写相匹配的字符(一个字符的大写、小写、标题三者视为大小写相
// 匹配),这个函数遵循 Unicode 定义的大小写环绕匹配表。
//
// 例如:
// SimpleFold('A') = 'a'
// SimpleFold('a') = 'A'
//
// SimpleFold('K') = 'k'
// SimpleFold('k') = 'K' (开尔文符号)
// SimpleFold('K') = 'K'
//
// SimpleFold('1') = '1'
func SimpleFold(r rune) rune

程序示例:

func main() {s := "ΦφϕkKK"// 看看 s 里面是什么for _, c := range s {fmt.Printf("%x  ", c)}fmt.Println()// 大写,小写,标题 | 当前字符 -> 下一个匹配字符for _, v := range s {fmt.Printf("%c, %c, %c | %c -> %c\n",unicode.ToUpper(v),unicode.ToLower(v),unicode.ToTitle(v),v,unicode.SimpleFold(v),)}
}// 输出结果:
// 3a6  3c6  3d5  6b  4b  212a
// Φ, φ, Φ | Φ -> φ
// Φ, φ, Φ | φ -> ϕ
// Φ, ϕ, Φ | ϕ -> Φ
// K, k, K | k -> K
// K, k, K | K -> k
// K, k, K | K -> K
// ToUpper 将 r 转换为大写格式
// 优先使用指定的映射表 special
// 可用的 SpecialCase 参见 go/src/unicode/casetables.go。
func (special SpecialCase) ToUpper(r rune) rune// ToLower 将 r 转换为小写格式
// 优先使用指定的映射表 special
func (special SpecialCase) ToLower(r rune) rune// ToTitle 将 r 转换为 Title 格式
// 优先使用指定的映射表 special
func (special SpecialCase) ToTitle(r rune) rune// SpecialCase 表示特定语言的大小写映射,比如土耳其语。
// SpecialCase 的方法可以自定义标准映射(通过重写)。
type SpecialCase []CaseRange// CaseRange 表示一个简单的 Unicode 码点范围,用于大小写转换。
// 在 Lo 和 Hi 范围内的码点,如果要转换成大写,只需要加上 d[0] 即可
// 如果要转换为小写,只需要加上 d[1] 即可,如果要转换为 Title 格式,
// 只需要加上 d[2] 即可。
type CaseRange struct {Lo    uint32Hi    uint32Delta d // [3]rune
}// CaseRanges 中 Delta 数组的索引。
const (UpperCase = iotaLowerCaseTitleCaseMaxCase
)// 如果一个 CaseRange 中的 Delta 元素是 UpperLower,则表示这个 CaseRange 是
// 一个有着连续的大写小写大写小写的范围。也就是说,Lo 是大写,Lo+1 是小写,
// Lo+2 是大写,Lo+3 是小写 ... 一直到 Hi 为止。
const (UpperLower = MaxRune + 1 // 不是一个有效的 Delta 元素
)// CaseRanges is the table describing case mappings for all letters with
// non-self mappings.
var CaseRanges = _CaseRanges
var _CaseRanges = []CaseRangetype SpecialCase []CaseRange

程序示例:

func main() {s := "Hello 世界!"for _, r := range s {fmt.Printf("%c", unicode.SpecialCase(unicode.CaseRanges).ToUpper(r))} // HELLO 世界!for _, r := range s {fmt.Printf("%c", unicode.SpecialCase(unicode.CaseRanges).ToLower(r))} // hello 世界!for _, r := range s {fmt.Printf("%c", unicode.SpecialCase(unicode.CaseRanges).ToTitle(r))} // HELLO 世界!
}

转载博客链接及学习链接:http://www.cnblogs.com/golove/p/3273585.html

https://books.studygolang.com/The-Golang-Standard-Library-by-Example/chapter02/02.5.html

https://golang.org/pkg/unicode/#SpecialCase  官网标准库的链接。

Go语言 — Unicode码点包相关推荐

  1. C语言学习:剪切板UNICODE码使用

    前言 本文程序是基于作者另一篇文章的程序基础上做修改,链接:(17条消息) C语言学习:除去剪切板内容的换行与回车_余宁C的博客-CSDN博客 由于剪切板中普通的text数据是8位的,不能支持一些字符 ...

  2. 汉字编码(【Unicode】 【UTF-8】 【Unicode与UTF-8之间的转换】 【汉字 Unicode 编码范围】【中文标点Unicode码】【GBK编码】【批量获取汉字UNICODE码】)

    参考博客: Unicode与UTF-8互转(C语言实现):http://blog.csdn.net/tge7618291/article/details/7599902 汉字 Unicode 编码范围 ...

  3. 汉字编码与编程相关问题总结:ASCII、机内码、区位码、国标码、Unicode码他们之间是如何转换的

    一.ASCII.机内码.区位码.国标码.Unicode码他们之间是如何转换的,方程式是什么 汉字系统中的过程包括区位码.国标码和机内码,其中的转换关系如下: 1.区位码(十进制)转换成区位码(十六进制 ...

  4. 汉字编码与编程相关问题总结:ASCII、机内码、区位码、国标码、Unicode码是如何转换的

    一.ASCII.机内码.区位码.国标码.Unicode码他们之间是如何转换的,方程式是什么 汉字系统中的过程包括区位码.国标码和机内码,其中的转换关系如下: 1.区位码(十进制)转换成区位码(十六进制 ...

  5. 字符,字节和编码, ASCII码, DBCS码,SBCS码 与Unicode码

    字符,字节和编码, ASCII码, DBCS码,SBCS码 与Unicode码 http://www.regexlab.com/zh/encoding.htm 1. 编码问题的由来,相关概念的理解 1 ...

  6. 看不见的Unicode码让敏感词轻松逃过审核,谷歌IBM都中招

    丰色 发自 凹非寺 量子位 报道 | 公众号 QbitAI Unicode码作为全世界文字的统一编码,使用范围广,用它去对NLP模型做对抗攻击,可谓中招一大片. 就比如下面这个谷歌翻译: 文字部分都没 ...

  7. Visual Studio——多字节编码与Unicode码

    多字节字符与宽字节字符 1) char与wchar_t 我们知道C++基本数据类型中表示字符的有两种:char.wchar_t.  char叫多字节字符,一个char占一个字节,之所以叫多字节字符是因 ...

  8. Linux 如何安装程序的源代码软件包/源码程序包/源码包?

    文章目录 一.安装源码包的三个步骤 (一)执行命令 configure,进行配置/检测 (二)执行命令 make,编译源码 (三)执行命令 make install,安装软件 二.源码包安装示例 (一 ...

  9. golang中文文档_【译】Go 语言源码贡献官方指导文档

    以前给 Go 语言项目源码提交过一些 commits,期间阅读他们的官方指导文档的时候觉得这篇指导文档可以作为绝佳的关于大型软件项目的规范管理的参考,因为最近又提交了几个 commits,就又把这篇文 ...

最新文章

  1. 记录每个登陆用户的操作记录
  2. Java getBytes字符集问题
  3. flutter 刷脸_GitHub - nnnggel/baidu_face_plugin: 百度人脸识别和活体检测 Flutter 插件(目前版本仅支持 Android)...
  4. Java调用cmd命令 打开一个站点
  5. shell实例第3讲:获取随机8位数字
  6. 荣耀 6 安装 SD 卡,提示:SD卡已安全移除
  7. Eclipse Outline图标
  8. SAP Cloud for Customer的微信集成原型开发完毕后的效果示意图
  9. SSIS添加分区-动态
  10. 如何设置Windows 8开始画面中瓷贴最大行数
  11. 远哥跟你说 Spring的 classpath 通配符加载配置文件
  12. 转载CentOS7 yum 安装与配置MySQL5.7
  13. 2021年上半年网络工程师上午真题及答案解析
  14. html5与access连接数据库操作,access是一个什么数据库?
  15. sd卡驱动分析 linux,linux下SD卡驅動分析(一)
  16. 常见十大量化投资策略
  17. 浏览器打开pdf乱码
  18. 设计师的色彩理论,你知道不同色彩的秘密吗?
  19. 常用广告过滤规则整理
  20. [附源码]计算机毕业设计JAVA小说网站的设计与实现1

热门文章

  1. 独立研发股票分析系统
  2. 小本创业,要精打细算
  3. web html做菜单,Web元素设计之导航菜单
  4. CS61B sp2018笔记 | Exceptions, Iterators, Iterables
  5. 计算机电脑桌面不显示,解决办法:如果在打开计算机后桌面不显示,该怎么办...
  6. matlab中的fix()的用法
  7. 开发自己的UBB”代码“
  8. jpa使用findById
  9. IP冲突导致访问不了请求
  10. 个人业余无线电台管理暂行办法