你应该记住的一个UTF-8字符「EF BF BD」

utf-8是一种变长(1 byte ~ 6 bytes)的unicode字符集编码方案。所谓编码方案即讲字符集到码点(code point)的映射方式。

在众多的utf-8码点值中,除了ascii,你还应该记住「EF BF BD」,因为它是很多编程语言以及库中的备胎,即无效的码点值在编码的时候会默认用这个码点值进行替换,即utf-8中的超级「备胎」(REPLACEMENT CHARACTER)。

为什么会有无效的码点值?

UTF-8 Code Point

从上图可以知道,utf-8编码 并非连续的 。很多人会忽略这个细节。

什么时候会遇到无效的utf-8码点?

当你试图把一个无效的码点值作为utf-8码点处理时,就会产生无效的码点。此时,无效的码点会被替换为「EF BF BD」,然后进行后续处理,以避免无效码点可能引起的异常。很多语言对这种处理是 自动进行 的,比如golang:

为什么要记住这个码点

在「字符集敏感」的环境中,如果你的数据中出现了「EF BF BD」就应该警惕了,因为你传输的数据中途很可能经过了自动替换,收到的数据未必是原始的数据。这对于你排查一些奇怪的数据交换不一致问题是很有用的,很多时候,可能是你的最后一颗救命稻草。

例如,使用utf-8编码的xml文档进行数据交换,如果看见了「�」,毫无疑问数据源有非法码点值。网页中出现了「�」,那么肯定是html文档的编码不是合规的utf-8编码文档。文本编辑器中出现了「�」,那一定是你打开这个文档的姿势不对——又选错编码了。总之,当你看见超级备胎「�」的时候,不要觉得大事不妙,不要像遇到一般乱码那样惊慌失措,你应该轻轻弹一下鼠标上的灰尘,将之打回原形。


因为aws的账单,才意识到自己的vps已经很久没有折腾了,博客也已经长草,应该说已经长成灌木丛了。

这才意识到自己已经回成都快9个月了。

有人说,时间是把杀猪刀。这很公平。但是,即使哪天挨上了这杀猪刀,也希望自己是头优雅的猪。

而此时,2015已经过去1/4.

golang中接收者初探

今天使用net/http库做了一个简单的server. 遇到一个之前自己忽略的问题,觉得挺有意思,简单做一个笔记。

server通过调用

实现。需要传递一个Handler类型的接口进行request/response的处理。Handler接口定义如下:

一切都非常简单,于是花了一分钟,写了一个server:

看似一切都没有问题的样子……但是却编译错误:

原来是类型不匹配的问题。具体来说,接收者的类型才是真正实现接口的类型。在本例中,接收者类型是*Myserver,myServer也必须是一个指针。fix后的代码如下:

「Golang server design pattern」学习笔记

花了近一周时间,把golang基本语法看了两遍。使用了两个资料:

  1. 「学习 Go 语言」,邢星翻译版。GitHub地址PDF版。资料比较精要,非常适合短时间入门。每个章节后的习题设计不错,考察知识点比较充分和全面,但是经常出现「越级」现象,即第x章的内容习题,往往需要你学习了第x+1,x+2章后的内容以后才能完成。
  2. Go语言程序设计」,Mark Summerfield. 虽然是七牛许式伟翻译,但是还是比较粗糙,逻辑错误和排版错误比较多,有人评价说这是许的一本黑书,姑且批判性的看吧。这本书每章的例子分量很重,值得花时间研读以及抄一下代码。

以上是题外话。我接下来的工作会逐步转向golang的服务器维护和开发。因此,除去语言本身,对design pattern是下一阶段要着重学习的。找到一个这方面的资料资料:Golang server design pattern,阅读笔记如下:

  1. golang采用CSP(Communication Sequential Processing)实现并行,类似于Unix管道的概念,但是golang中,CSP是双向的,管道是单向的。由于没有共享资源,因此程序员可以避免显式加锁。
  2. 收/发chan的本质是带锁的FIFO操作。
  3. 从C++观点来开,
    1. golang的一个目录就是一个namespace/class。同一目录中的所有文件中的变量、函数,相互可见。
    2. C++继承 => golang嵌入
    3. 类方法 => 接收者
    4. 构造方法 => init()或者New()接口方法。golang中,一个目录/一个文件中可以有若干个init函数。
    5. void*/object => interface{}
    6. try()/catch() => panic()/recover()
  4. go项目组织原则:
    1. 一个目录下的所有.go文件爱你共同构成一个功能模块,为一个目的服务。
    2. 用层次话的方式组织工程。
    3. 尽可能多的使用goroutine处理并行,goroutine是很廉价的。
    4. 模块+接口 的方式构建项目,二不是OOP的方式。