Golang 与 PHP 的 json 序列化问题

Intro 最近在做 Golang 与 PHP 的 RPC 实现。因 PHP 业务端已上线稳定,Golang 方面则需要完全兼容。其中使用了 json 序列化,发现区别还是很大的,见下面代码。 $ php -a php > echo json_encode("<test我爱中国>"); "<test\u6211\u7231\u4e2d\u56fd>" package main import ( "encoding/json" "fmt" ) func main() { st := "<test我爱中国>" res, err := json.Marshal(st) if err != nil { fmt.Println("json err:", err.Error()) } fmt.Printf("json is: %s", string(res)) // json is: "\u003ctest我爱中国\u003e" } PHP 默认的 json_encode() 函数会把多字节字符转成 \uXXXX 当然通过设置 JSON_UNESCAPED_UNICODE 可以解决这个问题。这里不动 PHP 代码。 Golang 这里用 json 包的 Marshal 方法实现序列化,对多字节字符是不进行处理的。但是这个方法出于安全考虑会将"<", “>”, “&“这三个字符转成 \uXXXX 形式。这还不是最魔幻的,这个方法没有可选参数进行设置。 ...

December 23, 2019 · 3 min · 467 words · Nick

PHP7 数组排序函数源码解析

今天来看看经常使用的数组排序函数如 sort, rsort, asort, arsort, ksort, krsort 。话不多说直接找 sort 函数吧。 在 php7.3 源码中搜索 PHP_FUNCTION(sort) 可以搜到如下 其中 .h 文件是C语言的头文件,直接打开 .c 文件。 sort 函数如下,其中我加了一点注释。 PHP_FUNCTION(sort) { zval *array; zend_long sort_type = PHP_SORT_REGULAR; // 默认的排序规则 compare_func_t cmp; // 这里开始接请求参数 ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_ARRAY_EX(array, 0, 1) Z_PARAM_OPTIONAL Z_PARAM_LONG(sort_type) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); // 根据排序规则获取使用的排序函数 cmp = php_get_data_compare_func(sort_type, 0); // 进行排序 if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 1) == FAILURE) { RETURN_FALSE; } RETURN_TRUE; } 不但 rsort, asort, arsort, ksort, krsort 这些函数在 array.c 文件中,PHP数组相关的也都在其中。 先说下 rsort, asort, arsort, ksort, krsort 函数内容与 sort 只有细微的差别。 ksort、krsort 是根据键排序所以排序规则获取排序函数用的是 php_get_key_compare_func 参数与 php_get_data_compare_func 是一样的。 php_get_data_compare_func、php_get_key_compare_func 函数第二个参数意思是是否降序排列,rsort、arsort、krsort 第二个参数都是1。 进行排序时 zend_hash_sort(Z_ARRVAL_P(array), cmp, 1) 第三个参数意思是是否重新排列索引, sort、rsort 传的都是1。 做个表格看下 ...

May 22, 2019 · 5 min · 935 words · Nick