一個位元(bit)可以是0,或者是1,8個位元(bit),組成一個位元組(byte),全為0時代表數字0,全為1時代表數字255,

一個位元組可以表示256個數字,兩個位元組可以表示65536個數字,

更多的位元組,可以有更多的組合,就可以表示更大的數值范圍,
整數可以這么存,那字符呢?一堆二進制的0和1,怎么也算不出字母A吧,不能直接表示,那就通過數字中轉一下,只要給它指定一個數值編號,要存盤字符時,就存盤這個數值,要讀取時,按照映射關系找到這個字符,

像這樣收錄許多字符然后給它們一一編號,得到一個字符編號對照表,這就是“字符集”,

ASCII字符集只收錄了128個字符,其擴展字符集也只有256個,(ASCII最初被設計的目的也只是用來映射英文體系所需要的字符)
這在只使用英文的國家貌似沒什么問題,但是隨著世界的互聯,其它非英語母語的國家該怎么辦呢?比如漢字、日文等,
針對漢字,最先設計了GB2312字符集、但是GB2312不包含繁體字,所以又設計了BIG5字符集,但是依然有很多字符沒有被收錄,其它國家的字體也不在其中

與其不斷推出收錄更多字符的字符集,還不如本著全球化統一標準的目的,制作一個通用字符集,Unicode學術學會就是這樣做的,這個字符集就是Unicode,它于1990年開始研發并于1994年正式公布,實作了跨語言跨平臺的文本轉換與處理,字符集促成了字符與二進制的合作,但是有了字符集就萬事大吉了嗎?那怎么存盤(eggo世界)這個內容呢?

直接的想法是,找到每個字符對應的編號,存成二進制,如果使用unicode字符集,拿到他們的編號,直接組合會得到這樣一大串二進制位

問題出現了,該怎么知道這一長串內容是要按照下面的方式劃分的呢?

也可以按照下面的方式劃分呀

所以,照搬編號的方式,行不通!!!
那現在我們可以知道了,編碼完成之后還需要解決的一個問題是如何劃分字符邊界,
其中一個方法可以這樣,不管編號多大多小,統一按照最長的編碼的來,位數不夠的高位補0嘛

這就是定長編碼,這樣就可以解決字符邊界的問題,但是可以發現,這樣就太浪費記憶體了,而且字符集收錄的符號越多,編號跨度就越大,定長編碼造成的浪費就越顯著,還得再想辦法,定長編碼不行,那就“變長編碼”,小編號少占位元組,大編號多占位元組,

但是怎么劃分字符邊界呢?來看一種解決方案,如果編號屬于[0,127],就占用一個位元組,且最高位固定標識為0,如果屬于[128,2047],就占用兩個位元組,且有固定標識位110和10,三個以及更多位元組的編碼也遵循這樣的規則

以二進制數字01100101,這個位元組最高位是零,就表示這個字符只占一個位元組,除去標識位,剩下的7位就是該字符的二進制編號,轉換成十進制就是101,對應字符e,“世”字同理,

這樣劃分字符就不成問題了,剛剛我們做的是解碼,現在來編碼試試,世界的“界”字在Unicode字符集中編號為30028,符合區間[2048,65535],所以要占用三位元組,使用下面這個模板,

然后將編號30028轉換成二進制01110101 01001100,再對應填到模板中

好的,這樣就編碼完成了, 我們剛剛用的其實就是UTF-8編碼,也就是Go語言默認的編碼方式,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/458602.html
標籤:Go
