<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>源码 on Nick's Blog</title><link>https://ibelieving.com/tags/%E6%BA%90%E7%A0%81/</link><description>Recent content in 源码 on Nick's Blog</description><generator>Hugo</generator><language>zh-cn</language><copyright>2014 ibelieving.com. All rights reserved.</copyright><lastBuildDate>Mon, 23 Dec 2019 22:32:00 +0800</lastBuildDate><atom:link href="https://ibelieving.com/tags/%E6%BA%90%E7%A0%81/index.xml" rel="self" type="application/rss+xml"/><item><title>Golang 与 PHP 的 json 序列化问题</title><link>https://ibelieving.com/posts/2019-12-23-golang_and_php_json/</link><pubDate>Mon, 23 Dec 2019 22:32:00 +0800</pubDate><guid>https://ibelieving.com/posts/2019-12-23-golang_and_php_json/</guid><description>&lt;h1 id="intro"&gt;Intro&lt;/h1&gt;
&lt;p&gt;最近在做 Golang 与 PHP 的 RPC 实现。因 PHP 业务端已上线稳定，Golang 方面则需要完全兼容。其中使用了 json 序列化，发现区别还是很大的，见下面代码。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ php -a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php &amp;gt; &lt;span style="color:#6639ba"&gt;echo&lt;/span&gt; json_encode&lt;span style="color:#0550ae"&gt;(&lt;/span&gt;&lt;span style="color:#0a3069"&gt;&amp;#34;&amp;lt;test我爱中国&amp;gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#0550ae"&gt;)&lt;/span&gt;&lt;span style="color:#1f2328"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#0a3069"&gt;&amp;#34;&amp;lt;test\u6211\u7231\u4e2d\u56fd&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-golang" data-lang="golang"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#cf222e"&gt;package&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;main&lt;/span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#cf222e"&gt;import&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;(&lt;/span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#0a3069"&gt;&amp;#34;encoding/json&amp;#34;&lt;/span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#0a3069"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#1f2328"&gt;)&lt;/span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#cf222e"&gt;func&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#6639ba"&gt;main&lt;/span&gt;&lt;span style="color:#1f2328"&gt;()&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;{&lt;/span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;st&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#0550ae"&gt;:=&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#0a3069"&gt;&amp;#34;&amp;lt;test我爱中国&amp;gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;res&lt;/span&gt;&lt;span style="color:#1f2328"&gt;,&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;err&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#0550ae"&gt;:=&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;json&lt;/span&gt;&lt;span style="color:#1f2328"&gt;.&lt;/span&gt;&lt;span style="color:#6639ba"&gt;Marshal&lt;/span&gt;&lt;span style="color:#1f2328"&gt;(&lt;/span&gt;&lt;span style="color:#1f2328"&gt;st&lt;/span&gt;&lt;span style="color:#1f2328"&gt;)&lt;/span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#cf222e"&gt;if&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;err&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#0550ae"&gt;!=&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#cf222e"&gt;nil&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;{&lt;/span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;fmt&lt;/span&gt;&lt;span style="color:#1f2328"&gt;.&lt;/span&gt;&lt;span style="color:#6639ba"&gt;Println&lt;/span&gt;&lt;span style="color:#1f2328"&gt;(&lt;/span&gt;&lt;span style="color:#0a3069"&gt;&amp;#34;json err:&amp;#34;&lt;/span&gt;&lt;span style="color:#1f2328"&gt;,&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;err&lt;/span&gt;&lt;span style="color:#1f2328"&gt;.&lt;/span&gt;&lt;span style="color:#6639ba"&gt;Error&lt;/span&gt;&lt;span style="color:#1f2328"&gt;())&lt;/span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;}&lt;/span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;fmt&lt;/span&gt;&lt;span style="color:#1f2328"&gt;.&lt;/span&gt;&lt;span style="color:#6639ba"&gt;Printf&lt;/span&gt;&lt;span style="color:#1f2328"&gt;(&lt;/span&gt;&lt;span style="color:#0a3069"&gt;&amp;#34;json is: %s&amp;#34;&lt;/span&gt;&lt;span style="color:#1f2328"&gt;,&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#6639ba"&gt;string&lt;/span&gt;&lt;span style="color:#1f2328"&gt;(&lt;/span&gt;&lt;span style="color:#1f2328"&gt;res&lt;/span&gt;&lt;span style="color:#1f2328"&gt;))&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#57606a"&gt;// json is: &amp;#34;\u003ctest我爱中国\u003e&amp;#34;&lt;/span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#1f2328"&gt;}&lt;/span&gt;&lt;span style="color:#fff"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;PHP 默认的 &lt;code&gt;json_encode()&lt;/code&gt; 函数会把多字节字符转成 &lt;code&gt;\uXXXX&lt;/code&gt; 当然通过设置 &lt;code&gt;JSON_UNESCAPED_UNICODE&lt;/code&gt; 可以解决这个问题。这里不动 PHP 代码。
Golang 这里用 json 包的 Marshal 方法实现序列化，对多字节字符是不进行处理的。但是这个方法出于安全考虑会将&amp;quot;&amp;lt;&amp;quot;, &amp;ldquo;&amp;gt;&amp;rdquo;, &amp;ldquo;&amp;amp;&amp;ldquo;这三个字符转成 &lt;code&gt;\uXXXX&lt;/code&gt; 形式。这还不是最魔幻的，这个方法没有可选参数进行设置。&lt;/p&gt;</description></item><item><title>PHP7 数组排序函数源码解析</title><link>https://ibelieving.com/posts/2019-05-22-php7_function_sort/</link><pubDate>Wed, 22 May 2019 19:14:33 +0800</pubDate><guid>https://ibelieving.com/posts/2019-05-22-php7_function_sort/</guid><description>&lt;p&gt;今天来看看经常使用的数组排序函数如 &lt;code&gt;sort, rsort, asort, arsort, ksort, krsort&lt;/code&gt; 。话不多说直接找 &lt;code&gt;sort&lt;/code&gt; 函数吧。&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;php7.3&lt;/code&gt; 源码中搜索 &lt;code&gt;PHP_FUNCTION(sort)&lt;/code&gt; 可以搜到如下&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://ibelieving.com/images/15584996147536.jpg"&gt;&lt;/p&gt;
&lt;p&gt;其中 &lt;code&gt;.h&lt;/code&gt; 文件是C语言的头文件，直接打开 &lt;code&gt;.c&lt;/code&gt; 文件。
&lt;code&gt;sort&lt;/code&gt; 函数如下，其中我加了一点注释。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PHP_FUNCTION(sort)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; zval *array;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; zend_long sort_type = PHP_SORT_REGULAR; // 默认的排序规则
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; compare_func_t cmp;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; // 这里开始接请求参数
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZEND_PARSE_PARAMETERS_START(1, 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Z_PARAM_ARRAY_EX(array, 0, 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Z_PARAM_OPTIONAL
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Z_PARAM_LONG(sort_type)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; // 根据排序规则获取使用的排序函数
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cmp = php_get_data_compare_func(sort_type, 0);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; // 进行排序
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 1) == FAILURE) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RETURN_FALSE;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RETURN_TRUE;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;不但 &lt;code&gt;rsort, asort, arsort, ksort, krsort&lt;/code&gt; 这些函数在 &lt;code&gt;array.c&lt;/code&gt; 文件中，&lt;a href="https://www.php.net/manual/zh/book.array.php"&gt;PHP数组&lt;/a&gt;相关的也都在其中。
先说下 &lt;code&gt;rsort, asort, arsort, ksort, krsort&lt;/code&gt; 函数内容与 &lt;code&gt;sort&lt;/code&gt; 只有细微的差别。
&lt;code&gt;ksort、krsort&lt;/code&gt; 是根据键排序所以排序规则获取排序函数用的是 &lt;code&gt;php_get_key_compare_func&lt;/code&gt; 参数与 &lt;code&gt;php_get_data_compare_func&lt;/code&gt; 是一样的。
&lt;code&gt;php_get_data_compare_func、php_get_key_compare_func&lt;/code&gt; 函数第二个参数意思是是否降序排列，&lt;code&gt;rsort、arsort、krsort&lt;/code&gt; 第二个参数都是1。
进行排序时 &lt;code&gt;zend_hash_sort(Z_ARRVAL_P(array), cmp, 1)&lt;/code&gt; 第三个参数意思是是否重新排列索引， &lt;code&gt;sort、rsort&lt;/code&gt; 传的都是1。
做个表格看下&lt;/p&gt;</description></item></channel></rss>