<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>step by step</title>
  <description>step by step - </description>
  <atom:link href="http://huyongde.github.io/feed.xml" rel="self" type="application/rss+xml"/>
  <link>http://huyongde.github.io</link>
  <lastBuildDate>Fri, 08 Mar 2024 04:18:44 +0000</lastBuildDate>
  <pubDate>Fri, 08 Mar 2024 04:18:44 +0000</pubDate>
  <ttl>1800</ttl>


  <item>
    <title>mysql 两阶段提交</title>
    <description>&lt;h1 id=&quot;什么是两阶段提交&quot;&gt;什么是两阶段提交&lt;/h1&gt;
&lt;p&gt;两阶段提交是mysql在使用innodb引擎时，为了提供crash-safe 能力而设计的，两阶段提交涉及两个日志
server层的逻辑日志 bin log(归档日志) 和 innodb引擎层的物理日志redo log , redolog 存在prepare和commit两个状态
bin log和redo log有啥区别呢？ 总结如下三点：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;redo log是InnoDB引擎特有的；binlog是MySQL的Server层实现的，所有引擎都可以使用。&lt;/li&gt;
  &lt;li&gt;redo log是物理日志，记录的是“在某个数据页上做了什么修改”；binlog是逻辑日志，记录的是这个语句的原始逻辑，比如“给ID=2这一行的c字段加1 ”。&lt;/li&gt;
  &lt;li&gt;redo log是循环写的，空间固定会用完；binlog是可以追加写入的。“追加写”是指binlog文件写到一定大小后会切换到下一个，并不会覆盖以前的日志。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;基于这两个日志， mysql 的一条更新语句会存在两阶段提交， 一条更新语句的主要流程是：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;server 执行器调用引擎层读接口找到要做更新的记录，如果对应的记录在引擎层的内存里，直接返回给执行器；否则，需要先从磁盘读入内存再返回&lt;/li&gt;
  &lt;li&gt;server 执行器拿到对应的记录后做更新并再调用引擎层的写接口&lt;/li&gt;
  &lt;li&gt;引擎层将更新的数据写入内存中，并记录redo log, 并且redo log状态标记为prepare, 然后给执行器返回成功，可以做事务提交了&lt;/li&gt;
  &lt;li&gt;server 层执行器生成操作的bin log ,并把bin log写入磁盘， 然后调用引擎层的事务提交接口，引擎层把redolog 的状态从prepare 更新为commit， 更新语句执行完成&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;用下图来表达更新语句中的两阶段提交&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/mysql-two-phase-commit.jpg&quot; alt=&quot;mysql&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;为什么两阶段提交可以提供crash-safe-能力&quot;&gt;为什么两阶段提交可以提供crash safe 能力&lt;/h1&gt;

&lt;p&gt;关于为什么两阶段提交可以保证crash safe，主要以下原因&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;如果在写redolog之前，就崩溃，那么redolog 和 binlog 中均未写入数据，数据可以保持一致性。&lt;/li&gt;
  &lt;li&gt;如果在写入redolog之后，即prepare状态的redolog，
 a. 在写入binlog之前，系统崩溃。当系统恢复时，prepare状态的redolog中的事务ID，binlog中不能被找到，即直接回滚redo log
 b. 在写入binlog之后，标记redolog为commit之前，系统崩溃。当系统恢复时，redo log的事务ID，在binlog中是可以被找到的，那么直接提交数据，标记redolog从prepare状态至commit状态&lt;/li&gt;
&lt;/ol&gt;

</description>
    <link>http://huyongde.github.io/2023/03/08/mysql-two-phase-commit.html</link>
    <guid>http://huyongde.github.io/2023/03/08/mysql-two-phase-commit</guid>
    <pubDate>Wed, 08 Mar 2023 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>golang中 select 关键字的实现</title>
    <description>&lt;h4 id=&quot;下图概括了select关键字的实现&quot;&gt;下图概括了select关键字的实现:&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;/image/go-select.png&quot; alt=&quot;select&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;select&quot;&gt;select&lt;/h2&gt;
&lt;p&gt;在go中，通过select可以实现等待多个channel达到就绪状态，select中的case都要关联到channel相关的读写操作。&lt;/p&gt;

&lt;p&gt;select 中每个case都会生成一个对应的scase结构体，结构体定义如下&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Select case descriptor.
// Known to compiler.
// Changes here must also be made in src/cmd/internal/gc/select.go's scasetype.
type scase struct {
    c           *hchan         // chan
    elem        unsafe.Pointer // data element
    kind        uint16  
    pc          uintptr // race pc (for race detector / msan)
    releasetime int64
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;case的类型有如下几种:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// scase.kind values.
// Known to compiler.
// Changes here must also be made in src/cmd/compile/internal/gc/select.go's walkselect.
const (
    caseNil = iota
    caseRecv
    caseSend
    caseDefault
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;编译阶段&quot;&gt;编译阶段&lt;/h3&gt;
&lt;p&gt;select对应的opType是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OSELECT&lt;/code&gt;, 当&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sop==OSELECT&lt;/code&gt;时，会调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;walkselect()&lt;/code&gt;，代码在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/cmd/compile/internal/gc/walk.go&lt;/code&gt;中， 如下&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// The result of walkstmt MUST be assigned back to n, e.g.
//  n.Left = walkstmt(n.Left)
func walkstmt(n *Node) *Node {
    if n == nil {
        return n
    }
    ......
     case OSELECT:
        walkselect(n)

    case OSWITCH:
        walkswitch(n)

    case ORANGE:
        n = walkrange(n)
    }

    if n.Op == ONAME {
        Fatalf(&quot;walkstmt ended up with name: %+v&quot;, n)
    }
    return n
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;其中省略了大部分代码。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;walkselect()&lt;/code&gt;定义在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/cmd/compile/internal/gc/select.go&lt;/code&gt;中，其中会调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;walkselectcases()&lt;/code&gt;,其中会生成一个scase的数组，
并调用运行时的函数&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selectgo()&lt;/code&gt;， 定义在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/runtime/select.go&lt;/code&gt;中&lt;/p&gt;

&lt;p&gt;walkselect()源码如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;func walkselect(sel *Node) {
    lno := setlineno(sel)
    if sel.Nbody.Len() != 0 {
        Fatalf(&quot;double walkselect&quot;)
    }

    init := sel.Ninit.Slice()
    sel.Ninit.Set(nil)

    init = append(init, walkselectcases(&amp;amp;sel.List)...)
    sel.List.Set(nil)

    sel.Nbody.Set(init)
    walkstmtlist(sel.Nbody.Slice())

    lineno = lno
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;walkselectcases&quot;&gt;walkselectcases()&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;walkselectcases()&lt;/code&gt;中会分如下几种情况处理select：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;select中不存在case, 直接堵塞&lt;/li&gt;
  &lt;li&gt;select中仅存在一个case&lt;/li&gt;
  &lt;li&gt;select中存在两个case，其中一个是default&lt;/li&gt;
  &lt;li&gt;其他select情况如: 包含多个case并且有default等&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;前三种情况不会走到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selectgo()&lt;/code&gt;的逻辑，最后一种多个case的情况会调用运行时函数&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selectgo()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;walkselectcases()&lt;/code&gt; 部分源码如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
func walkselectcases(cases *Nodes) []*Node {
    n := cases.Len()
    sellineno := lineno

    // optimization: zero-case select
    if n == 0 {
        return []*Node{mkcall(&quot;block&quot;, nil, nil)}
    }

    // optimization: one-case select: single op.
    // TODO(rsc): Reenable optimization once order.go can handle it.
    // golang.org/issue/7672.
    if n == 1 {
        cas := cases.First()
        setlineno(cas)
        l := cas.Ninit.Slice()
        ......
   	}
   	// optimization: two-case select but one is default: single non-blocking op.
    if n == 2 &amp;amp;&amp;amp; (cases.First().Left == nil || cases.Second().Left == nil) {
        var cas *Node
        var dflt *Node
        if cases.First().Left == nil {
            cas = cases.Second()
            dflt = cases.First()
        } else {
            dflt = cases.Second()
            cas = cases.First()
        }
        .......
    }
    var init []*Node

    // generate sel-struct
    lineno = sellineno
    selv := temp(types.NewArray(scasetype(), int64(n)))
    r := nod(OAS, selv, nil)
    r = typecheck(r, ctxStmt)
    init = append(init, r)

    order := temp(types.NewArray(types.Types[TUINT16], 2*int64(n)))
    r = nod(OAS, order, nil)
    r = typecheck(r, ctxStmt)
    init = append(init, r)

    // register cases
    for i, cas := range cases.Slice() {
        setlineno(cas)

        init = append(init, cas.Ninit.Slice()...)
        cas.Ninit.Set(nil)

        // Keep in sync with runtime/select.go.
        const (
            caseNil = iota
            caseRecv
            caseSend
            caseDefault
        )
        .......
    }


    // run the select
    lineno = sellineno
    chosen := temp(types.Types[TINT])
    recvOK := temp(types.Types[TBOOL])
    r = nod(OAS2, nil, nil)
    r.List.Set2(chosen, recvOK)
    fn := syslook(&quot;selectgo&quot;)
    r.Rlist.Set1(mkcall1(fn, fn.Type.Results(), nil, bytePtrToIndex(selv, 0), bytePtrToIndex(order, 0), nodintconst(int64(n))))
    r = typecheck(r, ctxStmt)
    init = append(init, r)

    // selv and order are no longer alive after selectgo.
    init = append(init, nod(OVARKILL, selv, nil))
    init = append(init, nod(OVARKILL, order, nil))

    // dispatch cases
    for i, cas := range cases.Slice() {
        setlineno(cas)

        cond := nod(OEQ, chosen, nodintconst(int64(i)))
        cond = typecheck(cond, ctxExpr)
        cond = defaultlit(cond, nil)

        r = nod(OIF, cond, nil)

        if n := cas.Left; n != nil &amp;amp;&amp;amp; n.Op == OSELRECV2 {
            x := nod(OAS, n.List.First(), recvOK)
            x = typecheck(x, ctxStmt)
            r.Nbody.Append(x)
        }

        r.Nbody.AppendNodes(&amp;amp;cas.Nbody)
        r.Nbody.Append(nod(OBREAK, nil, nil))
        init = append(init, r)
    }

    return init
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;运行时函数selectgo&quot;&gt;运行时函数selectgo()&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selectgo()&lt;/code&gt;的主要逻辑:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;随机生成轮询顺序&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poolorder&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;按照 channel 地址生成锁定顺序&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lockorder&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;根据 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poolorder&lt;/code&gt; 遍历所有的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;case&lt;/code&gt; 看是否有可以立即处理的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;channel&lt;/code&gt; 读写操作，有的话直接返回&lt;/li&gt;
  &lt;li&gt;创建 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudog&lt;/code&gt; 结构体，并加入到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chan&lt;/code&gt;的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sendq&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recvq&lt;/code&gt;,并通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gopark&lt;/code&gt; 触发调度器进行调度，当前协程进入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;waiting&lt;/code&gt;状态&lt;/li&gt;
  &lt;li&gt;堵塞并等待被唤醒&lt;/li&gt;
  &lt;li&gt;当前协程被唤醒时，再次按照 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lockorder&lt;/code&gt; 遍历所有的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;case&lt;/code&gt;,从中查找要处理的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudog&lt;/code&gt; 结构，并释放其他 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudog&lt;/code&gt;，并返回要处理的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudog&lt;/code&gt; 对应的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scase&lt;/code&gt; 的索引&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;通过源码中的注释，可以很清晰的看到如上的主要逻辑。&lt;/p&gt;

&lt;p&gt;详细代码在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/runtime/select.go&lt;/code&gt;中, 主要部分代码如下：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// selectgo implements the select statement.
//
// cas0 points to an array of type [ncases]scase, and order0 points to
// an array of type [2*ncases]uint16. Both reside on the goroutine's
// stack (regardless of any escaping in selectgo).
//
// selectgo returns the index of the chosen scase, which matches the
// ordinal position of its respective select{recv,send,default} call.
// Also, if the chosen scase was a receive operation, it reports whether
// a value was received.
func selectgo(cas0 *scase, order0 *uint16, ncases int) (int, bool) {
	......

	// generate permuted order
    for i := 1; i &amp;lt; ncases; i++ {
        j := fastrandn(uint32(i + 1))
        pollorder[i] = pollorder[j]
        pollorder[j] = uint16(i)
    }
    ......
    
     // sort the cases by Hchan address to get the locking order.
    // simple heap sort, to guarantee n log n time and constant stack footprint.
    for i := 0; i &amp;lt; ncases; i++ {
        j := i
        // Start with the pollorder to permute cases on the same channel.
        c := scases[pollorder[i]].c
        for j &amp;gt; 0 &amp;amp;&amp;amp; scases[lockorder[(j-1)/2]].c.sortkey() &amp;lt; c.sortkey() {
            k := (j - 1) / 2
            lockorder[j] = lockorder[k]
            j = k
        }
        lockorder[j] = pollorder[i]
    }
    .......

    // pass 1 - look for something already waiting
    var dfli int
    var dfl *scase
    var casi int
    var cas *scase
    var recvOK bool
    for i := 0; i &amp;lt; ncases; i++ {
    	......
    }
    ......

    // pass 2 - enqueue on all chans
    gp = getg()
    if gp.waiting != nil {
        throw(&quot;gp.waiting != nil&quot;)
    }
    nextp = &amp;amp;gp.waiting
    for _, casei := range lockorder {
    	......
    }
    ......


    // wait for someone to wake us up
    gp.param = nil
    gopark(selparkcommit, nil, waitReasonSelect, traceEvGoBlockSelect, 1)

    sellock(scases, lockorder)

    gp.selectDone = 0
    sg = (*sudog)(gp.param)
    gp.param = nil

    // pass 3 - dequeue from unsuccessful chans
    // otherwise they stack up on quiet channels
    // record the successful case, if any.
    // We singly-linked up the SudoGs in lock order.
    casi = -1
    cas = nil
    sglist = gp.waiting
    // Clear all elem before unlinking from gp.waiting.
    for sg1 := gp.waiting; sg1 != nil; sg1 = sg1.waitlink {
        sg1.isSelect = false
        sg1.elem = nil
        sg1.c = nil
    }
    gp.waiting = nil

    for _, casei := range lockorder {
    	......
    }
    ......

retc:
    if cas.releasetime &amp;gt; 0 {
        blockevent(cas.releasetime-t0, 1)
    }
    return casi, recvOK

sclose:
    // send on closed channel
    selunlock(scases, lockorder)
    panic(plainError(&quot;send on closed channel&quot;))
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如上是对golang中select实现的梳理，可以参考。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;go版本为: go version go1.12.12 darwin/amd64&lt;/p&gt;
&lt;/blockquote&gt;
</description>
    <link>http://huyongde.github.io/2019/10/26/golang-select.html</link>
    <guid>http://huyongde.github.io/2019/10/26/golang-select</guid>
    <pubDate>Sat, 26 Oct 2019 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>golang中 make 和 new 关键字的实现</title>
    <description>&lt;h4 id=&quot;下图概括了make-和-new-关键字的实现&quot;&gt;下图概括了make 和 new 关键字的实现:&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;/image/golang_make_new.png&quot; alt=&quot;make_new&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;make-vs-new&quot;&gt;make vs new&lt;/h2&gt;

&lt;h3 id=&quot;make&quot;&gt;make&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;ol&gt;
      &lt;li&gt;make 对应的 OP type 是 OMAKE, 在类型检查阶段 typecheck1()函数会把 OMAKE 根据参数类型调整为 OMAKESLICE或 OMAKECHAN或 OMAKEMAP&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;cmd/compile/internal/gc/typecheck.go&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;ol&gt;
      &lt;li&gt;walkexpr()函数会通过 mkcall()函数把 OMAKECHAN、OMAKEMAP、OMAKESLICE 分别调用运行时函数 makechan、makemap、makeslice&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;cmd/compile/internal/gc/walk.go&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;返回值&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;makeslice 返回 slice 结构体&lt;/p&gt;

        &lt;p&gt;runtime/slice.go&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;makemap 返回 hmap 结构体的指针&lt;/p&gt;

        &lt;p&gt;runtime/hashmap.go&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;makechan 返回hchan 结构体的指针&lt;/p&gt;

        &lt;p&gt;runtime/chan.go&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;makeslice&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;通过 mallocgc分配内存并返回 slice 结构体&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;makemap&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;通过 mallocgc 申请内存创建 hmap 结构体，并为 hmap 结构体的成员buckets 和 overflow申请内存，最后返回 hmap 的指针&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;makechan&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;makechan 做了优化，分了三类 case,&lt;/li&gt;
      &lt;li&gt;
        &lt;ol&gt;
          &lt;li&gt;chan 无 buf 时，只需要分配 hchan 结构体的大小并返回 hchan的指针&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;ol&gt;
          &lt;li&gt;chan 有 buf并且元素是无指针的基础类型，把 hchan 结构体和  hchan 中buf的空间分配在一个连续的内存空间中，并返回 hchan 的指针&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;ol&gt;
          &lt;li&gt;chan 有 buf 并且元素含指针，分别分配 hchan 结构体和结构体中 buf 的内存&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;new&quot;&gt;new&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;new 对应的 OP type 是 ONEW,walkexpr()会根据是否需要逃逸到堆上来分别处理，需要逃逸到堆上的话调用 callnew(),不需要的话直接在栈上分配&lt;/p&gt;

    &lt;p&gt;cmd/compile/internal/gc/walk.go&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;callnew()中会通过 mkcall1函数调用运行时函数 newobject()&lt;/p&gt;

    &lt;p&gt;cmd/compile/internal/gc/walk.go&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;newobject()中只是调用了 mallocgc 申请内存并返回内存的指针,mallocgc()函数中涉及到了 go 的内存管理机制，后面详细介绍&lt;/p&gt;

    &lt;p&gt;runtime/malloc.go&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;返回值: new 的返回值都是指针&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;如上是对 make 和 new 实现的整理，可参考着去看下golang 源码，加深理解。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;go-的版本信息&quot;&gt;go 的版本信息&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ go version
go version go1.13 darwin/amd64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
    <link>http://huyongde.github.io/2019/10/17/golang-make-new.html</link>
    <guid>http://huyongde.github.io/2019/10/17/golang-make-new</guid>
    <pubDate>Thu, 17 Oct 2019 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>go服务优化技巧</title>
    <description>&lt;h3 id=&quot;简介&quot;&gt;简介&lt;/h3&gt;
&lt;p&gt;本文介绍go服务可能会用到的几个优化技巧&lt;/p&gt;

&lt;h3 id=&quot;技巧1-syncpool-池化某些对象实现复用&quot;&gt;技巧1: sync.Pool 池化某些对象，实现复用&lt;/h3&gt;
&lt;p&gt;池化后进行对象复用，可以减少对象重复创建的开销，并且可以减轻gc的压力。&lt;/p&gt;

&lt;p&gt;使用示例:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package main

import (
	&quot;fmt&quot;
	&quot;sync&quot;
)

var bufpool = sync.Pool{
	New: func() interface{} {
		buf := make([]byte, 0, 512)
		return &amp;amp;buf
	},
}

func main() {
	b1 := *bufpool.Get().(*[]byte)
	b1 = append(b1, []byte(&quot;aaaaa&quot;)...)
	fmt.Println(b1, len(b1), cap(b1))
	fmt.Printf(&quot;%p, %p \n&quot;, b1, &amp;amp;b1)
	bufpool.Put(&amp;amp;b1)
	b2 := *bufpool.Get().(*[]byte)
	fmt.Println(b2, len(b2), cap(b2))
	fmt.Printf(&quot;%p, %p \n&quot;, b2, &amp;amp;b2)
	bufpool.Put(&amp;amp;b2)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;示例程序输出结果为:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[97 97 97 97 97] 5 512
0xc4200a6000, 0xc4200a2020
[97 97 97 97 97] 5 512
0xc4200a6000, 0xc4200a20a0

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;b2和b1对应的底层页数组的地址是一致的，并且b2从pool里取出来时，保留了b1的值，这样是不合理的，
b2的预期值应该是个空对象，所以在put之前需要把对象归零。
如上示例，在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bufpoo.Put(&amp;amp;b1)&lt;/code&gt; 之前增加&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b1=b1[0:0]&lt;/code&gt; 后输出结果如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[97 97 97 97 97] 5 512
0xc420096000, 0xc42000a060
[] 0 512
0xc420096000, 0xc42000a0e0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;符合预期&lt;/p&gt;

&lt;h3 id=&quot;技巧2-避免用带有指针的结构体对象做大map的key&quot;&gt;技巧2: 避免用带有指针的结构体对象做大map的key&lt;/h3&gt;
&lt;p&gt;用带指针的对象做map的key, 在gc时会耗费更多的时间，因为gc需要根据指针去遍历所有的数据。
比如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map[string]int&lt;/code&gt; string 做map的key，string在go里用如下结构体实现:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;type StringHeader struct {
    Data uintptr
    Len  int
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;详细介绍在&lt;a href=&quot;https://golang.org/src/reflect/value.go?s=56526:56578#L1873&quot;&gt;StringHeader&lt;/a&gt;
string中是包含指针的，所以相比用无指针的对象做key，gc会更耗时。&lt;/p&gt;
&lt;h4 id=&quot;示例&quot;&gt;示例:&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package main

import (
    &quot;fmt&quot;
    &quot;runtime&quot;
    &quot;strconv&quot;
    &quot;time&quot;
)

const numElements = 1000000

var foo = map[string]int{}

func case1() {
    for i := 0; i &amp;lt; numElements; i++ {
        foo[strconv.Itoa(i)] = i
    }

}

var foo2 = map[int]int{}

func case2() {
    for i := 0; i &amp;lt; numElements; i++ {
        foo2[i] = i
    }
}
func timeGC() {
    t := time.Now()
    runtime.GC()
    fmt.Println(&quot;gc took time:&quot;, time.Since(t))
}
func main() {
    case1()
    //case2()
    for {
        timeGC()
        time.Sleep(1 * time.Second)
    }

}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;注释case2()， 打开case1()时，输出如下:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gc took time: 40.927788ms
gc took time: 40.265383ms
gc took time: 40.235497ms
gc took time: 40.562543ms
gc took time: 41.379995ms
gc took time: 40.582498ms
gc took time: 42.926792ms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;注释case1(), 打开case2()时，输出如下:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gc took time: 285.715µs
gc took time: 159.778µs
gc took time: 158.922µs
gc took time: 168.993µs
gc took time: 159.776µs
gc took time: 175.365µs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;gc耗时差别巨大。&lt;/p&gt;

&lt;p&gt;所以在使用大map时，尽量避免使用带指针的结构体对象做key。&lt;/p&gt;

&lt;h3 id=&quot;技巧3--使用-stringsbuilder-来拼接字符串&quot;&gt;技巧3:  使用 strings.Builder 来拼接字符串&lt;/h3&gt;
&lt;p&gt;Go 1.10 版本, 提供了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strings.Builder&lt;/code&gt; 来更高效的进行字符串的拼接，
Builder 底层实现是向一个byte 的 buffer 中不断写入数据.
Builder 实现在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/string/builder.go&lt;/code&gt; 中, 结构定义如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;type Builder struct {
    addr *Builder // of receiver, to detect copies by value
    buf  []byte
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;通过例子对比下性能差异&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// main.go
package main

import &quot;strings&quot;

var strs = []string{
	&quot;here's&quot;,
	&quot;a&quot;,
	&quot;some&quot;,
	&quot;long&quot;,
	&quot;list&quot;,
	&quot;of&quot;,
	&quot;strings&quot;,
	&quot;for&quot;,
	&quot;you&quot;,
}

func buildStrNaive() string {
	var s string

	for _, v := range strs {
		s += v
	}

	return s
}
func buildStrBuilder(grow bool) string {
	b := strings.Builder{}
	if grow {
		b.Grow(60)
	}
	for _, v := range strs {
		b.WriteString(v)
	}
	return b.String()
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// main_test.go
package main

import &quot;testing&quot;

func BenchmarkBuildStr(b *testing.B) {
	b.Run(&quot;Naive&quot;, func(b *testing.B) {
		for i := 0; i &amp;lt; b.N; i++ {
			buildStrNaive()
		}
	})
	b.Run(&quot;builder-0&quot;, func(b *testing.B) {
		for i := 0; i &amp;lt; b.N; i++ {
			buildStrBuilder(false)
		}
	})
	b.Run(&quot;builder-1&quot;, func(b *testing.B) {
		for i := 0; i &amp;lt; b.N; i++ {
			buildStrBuilder(true)
		}
	})
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go test -bench=. -benchmem&lt;/code&gt;进行基准测试，结果如下&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;goos: darwin
goarch: amd64
BenchmarkBuildStr/Naive-4         	 3424706	       374 ns/op	     216 B/op	       8 allocs/op
BenchmarkBuildStr/builder-0-4     	 7817630	       176 ns/op	     120 B/op	       4 allocs/op
BenchmarkBuildStr/builder-1-4     	17136417	        67.4 ns/op	      64 B/op	       1 allocs/op
PASS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Builder.Grow()&lt;/code&gt; 提前预分配空间的情况下性能提升了4倍, 即使不提前预分配空间也能提升一倍多。&lt;/p&gt;

&lt;h3 id=&quot;技巧4--使用strconv包替代fmt包&quot;&gt;技巧4:  使用strconv包替代fmt包&lt;/h3&gt;
&lt;p&gt;在把整数转为字符串时，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strconv.Itoa&lt;/code&gt;性能会比&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fmt.Sprintf&lt;/code&gt;好很多，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fmt.Sprintf&lt;/code&gt; 使用接口interface{}作为参数，存在如下缺点:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;失去了类型安全&lt;/li&gt;
  &lt;li&gt;变量转为interface{}时会进行内存申请&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;接下来， 通过基准测试对比两种把整数转为字符串的方法&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package main

import (
	&quot;fmt&quot;
	&quot;strconv&quot;
)

func strconvFmt(b int) string {
	return strconv.Itoa(b)
}
func fmtFmt(b int) string {
	return fmt.Sprintf(&quot;%d&quot;, b)
}
func main(){}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;test文件:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;func BenchmarkFmt(b *testing.B) {
	big := 10000
	small := 10
	b.Run(&quot;strconv_small&quot;, func(b *testing.B) {
		for i := 0; i &amp;lt; b.N; i++ {
			strconvFmt(small)
		}
	})
	b.Run(&quot;strconv_big&quot;, func(b *testing.B) {
		for i := 0; i &amp;lt; b.N; i++ {
			strconvFmt(big)
		}
	})
	b.Run(&quot;fmt.Sprintf_small&quot;, func(b *testing.B) {
		for i := 0; i &amp;lt; b.N; i++ {
			fmtFmt(small)
		}
	})
	b.Run(&quot;fmt.Sprintf_big&quot;, func(b *testing.B) {
		for i := 0; i &amp;lt; b.N; i++ {
			fmtFmt(big)
		}
	})

}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go test -bench=BenchmarkFmt -benchmem&lt;/code&gt;得到如下结果&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;goos: darwin
goarch: amd64
BenchmarkFmt/strconv_small-4         	305850991	         3.92 ns/op	       0 B/op	       0 allocs/op
BenchmarkFmt/strconv_big-4           	30948387	        32.7 ns/op	       5 B/op	       1 allocs/op
BenchmarkFmt/fmt.Sprintf_small-4     	10915570	       105 ns/op	      16 B/op	       2 allocs/op
BenchmarkFmt/fmt.Sprintf_big-4       	10358809	       113 ns/op	      16 B/op	       2 allocs/op
PASS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strconv.Itoa&lt;/code&gt;的性能是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fmt.Sprintf&lt;/code&gt;的3倍多，并且&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strconv.Itoa&lt;/code&gt;在处理绝对值小于100的整数时做了优化，
不需要进行alloc操作，性能更高。详情可以看&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/strconv/itoa.go&lt;/code&gt;中的代码。&lt;/p&gt;

&lt;h3 id=&quot;技巧5-byte-转-string-时用-unsafe-包&quot;&gt;技巧5: []byte 转 string 时，用 unsafe 包&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string(byteSlice)&lt;/code&gt; 把&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]byte&lt;/code&gt; 转为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt; 对应的是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OARRAYBYTESTR&lt;/code&gt;操作 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/cmd/compile/internal/gc/walk.go&lt;/code&gt;,&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/cmd/compile/internal/gc/syntax.go&lt;/code&gt;)，
此操作在编译阶段会映射成运行时函数&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slicebytetostring&lt;/code&gt;,  此函数定义在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/runtime/string.go&lt;/code&gt; 中， 函数中需要进行内存申请，性能会有影响。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Buf is a fixed-size buffer for the result,
// it is not nil if the result does not escape.
func slicebytetostring(buf *tmpBuf, b []byte) (str string) {
    l := len(b)
    if l == 0 {
        // Turns out to be a relatively common case.
        // Consider that you want to parse out data between parens in &quot;foo()bar&quot;,
        // you find the indices and convert the subslice to string.
        return &quot;&quot;
    }

    var p unsafe.Pointer
    if buf != nil &amp;amp;&amp;amp; len(b) &amp;lt;= len(buf) {
        p = unsafe.Pointer(buf)
    } else {
        p = mallocgc(uintptr(len(b)), nil, false)
    }
    stringStructOf(&amp;amp;str).str = p
    stringStructOf(&amp;amp;str).len = len(b)
    memmove(p, (*(*slice)(unsafe.Pointer(&amp;amp;b))).array, uintptr(len(b)))
    return
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;下面通过基准测试对比下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;func BenchmarkTostr(b *testing.B) {
	bs := []byte(&quot;hello go&quot;)
	var str string
	b.Run(&quot;unsafe&quot;, func(b *testing.B) {
		for i := 0; i &amp;lt; b.N; i++ {
			str = *(*string)(unsafe.Pointer(&amp;amp;bs))
		}

	})
	b.Run(&quot;normal&quot;, func(b *testing.B) {
		for i := 0; i &amp;lt; b.N; i++ {
			str = string(bs)
		}

	})
	fmt.Println(str)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;基准测试结果:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;goos: darwin
goarch: amd64
BenchmarkTostr/unsafe-4         	1000000000	         0.789 ns/op	       0 B/op	       0 allocs/op
BenchmarkTostr/normal-4         	64188240	        16.3 ns/op	       8 B/op	       1 allocs/op
hello go
PASS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;从测试结果看，多了一次内存分配，性能差了20多倍
所以在某些情况下，可以考虑使用 unsafe 包实现&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]byte&lt;/code&gt; 转为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;说明&quot;&gt;说明&lt;/h3&gt;
&lt;p&gt;go 的版本信息为:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ go version
go version go1.13 darwin/amd64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://stephen.sh/posts/quick-go-performance-improvements&quot;&gt;Simple techniques to optimise Go programs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    <link>http://huyongde.github.io/2019/06/20/go-optimise.html</link>
    <guid>http://huyongde.github.io/2019/06/20/go-optimise</guid>
    <pubDate>Thu, 20 Jun 2019 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>go unsafe 注释翻译和实践</title>
    <description>&lt;h3 id=&quot;背景&quot;&gt;背景&lt;/h3&gt;
&lt;p&gt;翻译go unsafe包中的部分注释，学习unsafe包的使用&lt;/p&gt;

&lt;p&gt;https://golang.org/src/unsafe/unsafe.go&lt;/p&gt;

&lt;h3 id=&quot;注释翻译&quot;&gt;注释翻译&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
	Package unsafe contains operations that step around the type safety of Go programs.

	Packages that import unsafe may be non-portable and are not protected by the
	Go 1 compatibility guidelines.

*/
unsafe 包包含了可以绕开go语言类型安全的一些操作。
引用了unsafe包的包可能是不可移植的、并且不受go兼容性指南的保护。

package unsafe


// ArbitraryType is here for the purposes of documentation only and is not actually
// part of the unsafe package. It represents the type of an arbitrary Go expression.
这里的ArbitraryType 仅仅是为了文档目的，实际上它不是unsafe包的一部分。它可以表示任意go表达式的类型

type ArbitraryType int

// Pointer represents a pointer to an arbitrary type. There are four special operations
// available for type Pointer that are not available for other types:
Pointer 表示指向任意类型的指针。Pointer 有四种特殊操作，这四种特殊操作不适用于其他类型。
//	- A pointer value of any type can be converted to a Pointer.
//	- A Pointer can be converted to a pointer value of any type.
//	- A uintptr can be converted to a Pointer.
//	- A Pointer can be converted to a uintptr.
- 任何类型的指针都可以被转换为Pointer
- Pointer可以被转换为任何类型的指针
- uintptr可以被转换为Pointer
- Pointer可以被转换为uintptr

// Pointer therefore allows a program to defeat the type system and read and write
// arbitrary memory. It should be used with extreme care.
因此，Pointer允许程序打破类型系统并读写任意内存。应该特别小心的使用Pointer

//
// The following patterns involving Pointer are valid.

// Code not using these patterns is likely to be invalid today
// or to become invalid in the future.
// Even the valid patterns below come with important caveats.
以下涉及Pointer的模式是有效的
未使用这些模式的代码现在是无效的，或者未来会变为无效。
即使下面这些有效的模式也有重要的注意事项。

//
// Running &quot;go vet&quot; can help find uses of Pointer that do not conform to these patterns,
// but silence from &quot;go vet&quot; is not a guarantee that the code is valid.
运行go vet可以帮助找到不符合这些模式的Pointer的用法，但是go vet 的沉默并不能保证代码是有效的。
//
// (1) Conversion of a *T1 to Pointer to *T2.
(1) *T1 转换为Pointer至*T2
//
// Provided that T2 is no larger than T1 and that the two share an equivalent
// memory layout, this conversion allows reinterpreting data of one type as
// data of another type. An example is the implementation of
// math.Float64bits:
//
//	func Float64bits(f float64) uint64 {
//		return *(*uint64)(unsafe.Pointer(&amp;amp;f))
//	}
//
// (2) Conversion of a Pointer to a uintptr (but not back to Pointer).
(2) Pointer转换为uintptr, 但不转换回Pointer
//
// Converting a Pointer to a uintptr produces the memory address of the value
// pointed at, as an integer. The usual use for such a uintptr is to print it.
将Pointer转换为uintptr会产生指针所指向值得内存地址，作为整数。
uintptr的通常用处是打印它。
//
// Conversion of a uintptr back to Pointer is not valid in general.
通常情况下，uintptr转换回Pointer是无效的。
//
// A uintptr is an integer, not a reference.
uintptr是个整数，不是引用。
// Converting a Pointer to a uintptr creates an integer value
// with no pointer semantics.
把Pointer转换为uintptr会创建一个无指针语义的整数。
// Even if a uintptr holds the address of some object,
// the garbage collector will not update that uintptr's value
// if the object moves, nor will that uintptr keep the object
// from being reclaimed.
即使uintptr保存了某个对象的地址，如果对象移动了，垃圾回收器也不会更新
uintptr的值，uintptr也不会保持该对象不被回收。
//
// The remaining patterns enumerate the only valid conversions
// from uintptr to Pointer.
剩下的模式枚举了uintptr到Pointer的有效转换。

//
// (3) Conversion of a Pointer to a uintptr and back, with arithmetic.
(3) Pointer 转换为uintptr，计算之后再转换回来
//
// If p points into an allocated object, it can be advanced through the object
// by conversion to uintptr, addition of an offset, and conversion back to Pointer.
如果p是指向一个已分配的对象，p可以被推进访问这个对象，通过转换为uintptr，增加个偏移量后再转换为Pointer
//
//	p = unsafe.Pointer(uintptr(p) + offset)
//
// The most common use of this pattern is to access fields in a struct
// or elements of an array:
此模式最常见的用途是访问结构体中的某个字段或者数组的元素:
//
//	// equivalent to f := unsafe.Pointer(&amp;amp;s.f)
//	f := unsafe.Pointer(uintptr(unsafe.Pointer(&amp;amp;s)) + unsafe.Offsetof(s.f))
//
//	// equivalent to e := unsafe.Pointer(&amp;amp;x[i])
//	e := unsafe.Pointer(uintptr(unsafe.Pointer(&amp;amp;x[0])) + i*unsafe.Sizeof(x[0]))
//
// It is valid both to add and to subtract offsets from a pointer in this way.
// It is also valid to use &amp;amp;^ to round pointers, usually for alignment.
// In all cases, the result must continue to point into the original allocated object.
通过这种方式为指针增加或者减去偏移量都是有效的。
使用&amp;amp;^来四舍五入指针也是有效的，此操作通常用来做对齐。
在所有情况下，结果必须继续指向原始分配的对象。

//
// Unlike in C, it is not valid to advance a pointer just beyond the end of
// its original allocation:
//
//	// INVALID: end points outside allocated space.
//	var s thing
//	end = unsafe.Pointer(uintptr(unsafe.Pointer(&amp;amp;s)) + unsafe.Sizeof(s))
//
//	// INVALID: end points outside allocated space.
//	b := make([]byte, n)
//	end = unsafe.Pointer(uintptr(unsafe.Pointer(&amp;amp;b[0])) + uintptr(n))
//
// Note that both conversions must appear in the same expression, with only
// the intervening arithmetic between them:
请注意，两个转换必须出现在同一个表达式中，它们之间仅有介入的计算
//
//	// INVALID: uintptr cannot be stored in variable
//	// before conversion back to Pointer.
//	u := uintptr(p)
//	p = unsafe.Pointer(u + offset)
//
// (4) Conversion of a Pointer to a uintptr when calling syscall.Syscall.
调用syscall.Syscall时Pointer转换为uintptr
//
// The Syscall functions in package syscall pass their uintptr arguments directly
// to the operating system, which then may, depending on the details of the call,
// reinterpret some of them as pointers.
// That is, the system call implementation is implicitly converting certain arguments
// back from uintptr to pointer.
//
// If a pointer argument must be converted to uintptr for use as an argument,
// that conversion must appear in the call expression itself:
//
//	syscall.Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(n))
//
// The compiler handles a Pointer converted to a uintptr in the argument list of
// a call to a function implemented in assembly by arranging that the referenced
// allocated object, if any, is retained and not moved until the call completes,
// even though from the types alone it would appear that the object is no longer
// needed during the call.
//
// For the compiler to recognize this pattern,
// the conversion must appear in the argument list:
//
//	// INVALID: uintptr cannot be stored in variable
//	// before implicit conversion back to Pointer during system call.
//	u := uintptr(unsafe.Pointer(p))
//	syscall.Syscall(SYS_READ, uintptr(fd), u, uintptr(n))
//
// (5) Conversion of the result of reflect.Value.Pointer or reflect.Value.UnsafeAddr
// from uintptr to Pointer.
reflect.Value.Pointer和reflect.Value.UnsafeAddr的返回结果从uintptr转换为Pointer
//
// Package reflect's Value methods named Pointer and UnsafeAddr return type uintptr
// instead of unsafe.Pointer to keep callers from changing the result to an arbitrary
// type without first importing &quot;unsafe&quot;. However, this means that the result is
// fragile and must be converted to Pointer immediately after making the call,
// in the same expression:
//
//	p := (*int)(unsafe.Pointer(reflect.ValueOf(new(int)).Pointer()))
//
// As in the cases above, it is invalid to store the result before the conversion:
//
//	// INVALID: uintptr cannot be stored in variable
//	// before conversion back to Pointer.
//	u := reflect.ValueOf(new(int)).Pointer()
//	p := (*int)(unsafe.Pointer(u))
//
// (6) Conversion of a reflect.SliceHeader or reflect.StringHeader Data field to or from Pointer.
reflect.SliceHeader或者reflect.StringHeader的Data字段转换到Pointer或者从Pointer转换
//
// As in the previous case, the reflect data structures SliceHeader and StringHeader
// declare the field Data as a uintptr to keep callers from changing the result to
// an arbitrary type without first importing &quot;unsafe&quot;. However, this means that
// SliceHeader and StringHeader are only valid when interpreting the content
// of an actual slice or string value.
//
//	var s string
//	hdr := (*reflect.StringHeader)(unsafe.Pointer(&amp;amp;s)) // case 1
//	hdr.Data = uintptr(unsafe.Pointer(p))              // case 6 (this case)
//	hdr.Len = n
//
// In this usage hdr.Data is really an alternate way to refer to the underlying
// pointer in the slice header, not a uintptr variable itself.
//
// In general, reflect.SliceHeader and reflect.StringHeader should be used
// only as *reflect.SliceHeader and *reflect.StringHeader pointing at actual
// slices or strings, never as plain structs.
// A program should not declare or allocate variables of these struct types.
//
//	// INVALID: a directly-declared header will not hold Data as a reference.
//	var hdr reflect.StringHeader
//	hdr.Data = uintptr(unsafe.Pointer(p))
//	hdr.Len = n
//	s := *(*string)(unsafe.Pointer(&amp;amp;hdr)) // p possibly already lost
//
type Pointer *ArbitraryType
go的任意类型 Pointer

// Sizeof takes an expression x of any type and returns the size in bytes
// of a hypothetical variable v as if v was declared via var v = x.
// The size does not include any memory possibly referenced by x.
// For instance, if x is a slice, Sizeof returns the size of the slice
// descriptor, not the size of the memory referenced by the slice.
Sizeof 返回任意表达式x的大小，单位字节, 大小不包括表达式所指向的内存大小，
如果x是个切片，Sizeof返回的是切片描述符的大小，不是切片所指向内存的大小。

func Sizeof(x ArbitraryType) uintptr

// Offsetof returns the offset within the struct of the field represented by x,
// which must be of the form structValue.field. In other words, it returns the
// number of bytes between the start of the struct and the start of the field.
返回结构体内某个字段的偏移量，参数x必须是structValue.field这中格式。也就是说，
Offsetof返回了结构体开始位置和某个字段开始位置的偏移量， 单位字节
func Offsetof(x ArbitraryType) uintptr

// Alignof takes an expression x of any type and returns the required alignment
// of a hypothetical variable v as if v was declared via var v = x.
// It is the largest value m such that the address of v is always zero mod m.
// It is the same as the value returned by reflect.TypeOf(x).Align().
// As a special case, if a variable s is of struct type and f is a field
// within that struct, then Alignof(s.f) will return the required alignment
// of a field of that type within a struct. This case is the same as the
// value returned by reflect.TypeOf(s.f).FieldAlign().
返回表达式x需要的对齐大小，单位字节
func Alignof(x ArbitraryType) uintptr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;如上是基于源码中的注释进行的部分理解和翻译&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;示例&quot;&gt;示例&lt;/h3&gt;
&lt;p&gt;Sizeof, Offsetof, Alignof 示例&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;64位系统，注释部分为对应语句的输出结果&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;type X struct {
        a bool
        b int16
        c []int
}
x := X{}
fmt.Println(unsafe.Sizeof(x), unsafe.Alignof(x))
// 32 8
fmt.Println(unsafe.Sizeof(x.a), unsafe.Alignof(x.a), unsafe.Offsetof(x.a))
//  1, 1, 0
fmt.Println(unsafe.Sizeof(x.b), unsafe.Alignof(x.b), unsafe.Offsetof(x.b))
// 2, 2, 2
fmt.Println(unsafe.Sizeof(x.c), unsafe.Alignof(x.c), unsafe.Offsetof(x.c))
// 24, 8, 8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;说明&quot;&gt;说明&lt;/h3&gt;
&lt;p&gt;水平有限，翻译仅供参考，有问题欢迎交流。&lt;/p&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://golang.org/src/unsafe/unsafe.go&quot;&gt;unsafe source code &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.kancloud.cn/hartnett/gopl-zh/126066&quot;&gt;go 语言圣经&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2019/06/16/go-package-unsafe.html</link>
    <guid>http://huyongde.github.io/2019/06/16/go-package-unsafe</guid>
    <pubDate>Sun, 16 Jun 2019 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>go append 使用陷阱</title>
    <description>&lt;h3 id=&quot;问题&quot;&gt;问题&lt;/h3&gt;
&lt;p&gt;请大家思考下如下代码的输出结果,&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package main

import &quot;fmt&quot;

func main() {
	a := []byte(&quot;aa&quot;)
	b := append(a, 'b')
	c := append(a, 'c')
	fmt.Println(string(a), len(a), cap(a), &amp;amp;a, &amp;amp;a[0])
	fmt.Println(string(b), len(b), cap(b), &amp;amp;b, &amp;amp;b[0])
	fmt.Println(string(c), len(c), cap(c), &amp;amp;c, &amp;amp;c[0])
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;实际输出结果为:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;aa 2 8 &amp;amp;[97 97] 0xc000016090
aac 3 8 &amp;amp;[97 97 99] 0xc000016090
aac 3 8 &amp;amp;[97 97 99] 0xc000016090
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;原因&quot;&gt;原因&lt;/h3&gt;

&lt;p&gt;b,c 通过a append后， a,b,c三个slice共用底层的数组，也就是说,
a,b,c三个slice的data字段指向同一个底层数组,
所以对任意一个slice的修改， 都会影响其他的slice的值。&lt;/p&gt;

&lt;p&gt;go中切片对应一个数据结构，如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;示例&quot;&gt;示例&lt;/h3&gt;
&lt;p&gt;如下代码Println和Printf输出是否一致呢？&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package main

import &quot;fmt&quot;

func main() {
	a := []byte(&quot;aa&quot;)
	b := append(a, 'b')
	c := append(a, 'c')
	fmt.Println(&amp;amp;a[0], &amp;amp;b[0], &amp;amp;c[0])
	fmt.Printf(&quot;%p %p %p\n&quot;, a, b, c)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;答案是一致的， 输出如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0xc000016090 0xc000016090 0xc000016090
0xc000016090 0xc000016090 0xc000016090
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这是因为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%p&lt;/code&gt; 对应slice时输出的是slice第一个元素的地址&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Slice:
%p	address of 0th element in base 16 notation, with leading 0x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;详见: &lt;a href=&quot;https://golang.org/pkg/fmt/&quot;&gt;fmt&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://studygolang.com/articles/19469&quot;&gt;深度解密Go语言之Slice&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://yourbasic.org/golang/gotcha-append/&quot;&gt;Why doesn’t append work every time?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    <link>http://huyongde.github.io/2019/06/15/go-gotcha-append.html</link>
    <guid>http://huyongde.github.io/2019/06/15/go-gotcha-append</guid>
    <pubDate>Sat, 15 Jun 2019 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>[golang踩的坑] ioutil.ReadAll 会清空对应Reader</title>
    <description>&lt;h3 id=&quot;问题&quot;&gt;问题&lt;/h3&gt;
&lt;p&gt;在golang web后台开发中，为了能够随机采集小部分请求case, 在框架里统一加了部分请求详细信息上报的逻辑，其中用到了，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;body, err := ioutil.ReadAll(ctx.Request.Body) &lt;/code&gt;来读取请求body里的内容，
后面业务逻辑中再取body内容时取出来的是空。&lt;/p&gt;

&lt;h3 id=&quot;解决方案&quot;&gt;解决方案&lt;/h3&gt;

&lt;p&gt;google了下，如下应该能解决这个问题&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;body, err := ioutil.ReadAll(ctx.Request.Body)
rdr := ioutil.NopCloser(bytes.NewBuffer(body))
ctx.Request.Body = rdr

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/23070876/reading-body-of-http-request-without-modifying-request-state&quot;&gt;reading-body-of-http-request-without-modifying-request-state&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://golang.org/src/net/http/httputil/dump.go#L26&quot;&gt;httputil&lt;/a&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2019/05/26/golang-ioutil.ReadAll.html</link>
    <guid>http://huyongde.github.io/2019/05/26/golang-ioutil.ReadAll</guid>
    <pubDate>Sun, 26 May 2019 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>nginx proxy_cache指令集详解</title>
    <description>&lt;h3 id=&quot;介绍&quot;&gt;介绍&lt;/h3&gt;

&lt;p&gt;在使用nginx做反向代理时, 部分业务场景可能可以使用proxy_cache来降低后端的压力，
nginx 提供了丰富的指令来配置符合业务场景的cache策略。&lt;/p&gt;

&lt;p&gt;下面分别介绍下nginx proxy_cache相关的指令和用法&lt;/p&gt;

&lt;h3 id=&quot;指令介绍&quot;&gt;指令介绍&lt;/h3&gt;

&lt;h4 id=&quot;1-proxy_cache&quot;&gt;1. proxy_cache&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_cache zone | off;
Default: proxy_cache off;
Context: http, server, location
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;指令&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache&lt;/code&gt; 用来配置用来做cache的一块内存区域，也可以用来关闭cache功能, 
参数为off时关闭当前配置块中的cache功能。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache&lt;/code&gt; 可以在http, server 以及location配置块中使用&lt;/p&gt;

&lt;h4 id=&quot;2-proxy_cache_background_update&quot;&gt;2. proxy_cache_background_update&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_cache_background_update on | off;
Default: proxy_cache_background_update off;
Context: http, server, location
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_background_update&lt;/code&gt; 用来控制当给用户返回一个过期的陈旧cache时
是否可以通过一个后台的子请求来更新当前cache, 需要和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_use_stale&lt;/code&gt; 指令配合使用&lt;/p&gt;

&lt;h4 id=&quot;3-proxy_cache_use_stale&quot;&gt;3. proxy_cache_use_stale&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | http_429 | off ...;
Default: proxy_cache_use_stale off;
Context: http, server, location
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_use_stale&lt;/code&gt; 来配置在请求后端时，出现那些情况，可以用一个过期的陈旧cache返回给用户
此指令的参数和proxy_next_upstream是基本一致的，额外增加了updating参数，
updating参数是指当正在更新一个cache时，对这个cache的请求可以返回一个陈旧的版本。&lt;/p&gt;

&lt;h4 id=&quot;4-proxy_cache_valid&quot;&gt;4. proxy_cache_valid&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_cache_valid [code ...] time;
Default: —
Context: http, server, location
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_valid&lt;/code&gt; 指令用来配置每个类型状态码的cache有效时间，示例:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;proxy_cache_valid 200 302 10m; ## 200 302 状态码，cache有效期10分钟
proxy_cache_valid 404 1m; ## 404 状态码，cache 1分钟 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h5 id=&quot;code-参数介绍&quot;&gt;code 参数介绍:&lt;/h5&gt;
&lt;ol&gt;
  &lt;li&gt;code参数时可以省略的，省略时code默认值是200 301 302&lt;/li&gt;
  &lt;li&gt;code参数取值为any时，表示所有的请求都会被cache&lt;/li&gt;
&lt;/ol&gt;

&lt;h5 id=&quot;需要注意的地方&quot;&gt;需要注意的地方&lt;/h5&gt;
&lt;ol&gt;
  &lt;li&gt;可以通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X-Accel-Expires&lt;/code&gt; 头来设置返回结果的cache时间，取值为0表示不做作cache, 取值如果以@开头，
表示在某个时间点之前有效，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X-Accel-Expires&lt;/code&gt;比&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_valid&lt;/code&gt;指令优先级高&lt;/li&gt;
  &lt;li&gt;可以通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Expires&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cache-Control&lt;/code&gt; 设置cache策略&lt;/li&gt;
  &lt;li&gt;带有&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Set-Cookie&lt;/code&gt;头的请求不会被cache&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Vary&lt;/code&gt; 头的取值为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;时，返回结果不会被cache, 其他取值时，可以被cache&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;上面介绍的返回头，可以通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_ignore_headers&lt;/code&gt; 来禁用&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;5-proxy_cache_bypass&quot;&gt;5. proxy_cache_bypass&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_cache_bypass string ...;
Default: —
Context: http, server, location
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_bypass&lt;/code&gt; 用来配置那些请求不使用cache, 
当配置的参数中，有一个值不为0或者不为空时，这个请求就不使用cache&lt;/p&gt;

&lt;h4 id=&quot;6-proxy_no_cache&quot;&gt;6. proxy_no_cache&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_no_cache string ...;
Default: —
Context: http, server, location

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_no_cache&lt;/code&gt; 用来配置那些请求后端的结果不存储到cache
当配置的参数中，有一个值不为0或者不为空时，这个请求，请求后端获取的结果就存储到cache中&lt;/p&gt;

&lt;h4 id=&quot;7-proxy_cache_convert_head&quot;&gt;7. proxy_cache_convert_head&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_cache_convert_head on | off;
Default: proxy_cache_convert_head on;
Context: http, server, location
This directive appeared in version 1.9.7.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_convert_head&lt;/code&gt; 用来配置是否把head请求转为get请求，来做cache， 当取值为off时，
需要把&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$request_method&lt;/code&gt;加到cache_key的配置指令中&lt;/p&gt;

&lt;h4 id=&quot;8-proxy_cache_key&quot;&gt;8. proxy_cache_key&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_cache_key string;
Default: proxy_cache_key $scheme$proxy_host$request_uri;
Context: http, server, location
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_key&lt;/code&gt; 用来配置cache时所使用的key, 示例:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;proxy_cache_key &quot;$host$request_uri $cookie_user&quot;;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;默认情况下，参数取值和下面的是接近的&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;proxy_cache_key $scheme$proxy_host$uri$is_args$args;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;通过请求协议、代理域名、请求路径以及参数来做cache_key&lt;/p&gt;

&lt;h4 id=&quot;9-proxy_cache_lock&quot;&gt;9. proxy_cache_lock&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_cache_lock on | off;
Default: proxy_cache_lock off;
Context: http, server, location
This directive appeared in version 1.1.12.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_lock&lt;/code&gt; 用来配置同一时刻更新cache, 是否限制只有一个请求更新cache。 取值为on时，
其他请求需要等待更新请求返回或者超时, 超时时间通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_lock_timeout&lt;/code&gt;来设置。&lt;/p&gt;

&lt;h4 id=&quot;10-proxy_cache_lock_timeout&quot;&gt;10. proxy_cache_lock_timeout&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_cache_lock_timeout time;
Default: proxy_cache_lock_timeout 5s;
Context: http, server, location
This directive appeared in version 1.1.12.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_lock_time&lt;/code&gt;指令用来给指令&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_lock&lt;/code&gt; 设置超时时间。
默认超时时间是5秒&lt;/p&gt;

&lt;h4 id=&quot;11-proxy_cache_lock_age&quot;&gt;11. proxy_cache_lock_age&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_cache_lock_age time;
Default: proxy_cache_lock_age 5s;
Context: http, server, location
This directive appeared in version 1.7.8.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;当配置&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_lock on;&lt;/code&gt; 时，proxy_cache_lock_age用来配置当最新的用来更新cache的请求在time时间为能完成cache更新时 ，
 允许另外一个请求取请求后端，来更新cache, 
默认是5秒&lt;/p&gt;

&lt;h4 id=&quot;12-proxy_cache_max_range_offset&quot;&gt;12. proxy_cache_max_range_offset&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax:	proxy_cache_max_range_offset number;
Default: —
Context: http, server, location
This directive appeared in version 1.11.6.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这个指令会设置一个字节单位的值，当http 分片请求的range大于设置的值时，这个分片请求不会命中cache,并且从后端请求的结果页不会更新cache.&lt;/p&gt;

&lt;h4 id=&quot;13-proxy_cache_methods&quot;&gt;13. proxy_cache_methods&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax:	proxy_cache_methods GET | HEAD | POST ...;
Default: proxy_cache_methods GET HEAD;
Context: http, server, location
This directive appeared in version 0.7.59.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_methods&lt;/code&gt; 用来配置那些http Method的请求会启用cache&lt;/p&gt;

&lt;h4 id=&quot;14-proxy_cache_min_uses&quot;&gt;14. proxy_cache_min_uses&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax:	proxy_cache_min_uses number;
Default: proxy_cache_min_uses 1;
Context: http, server, location
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_min_uses&lt;/code&gt; 用来设置同样请求被请求多少次之后会写入到cache, 默认值时1,
即所有满足配置的请求的返回结果都会写入cache&lt;/p&gt;

&lt;h4 id=&quot;15-proxy_cache_path&quot;&gt;15. proxy_cache_path&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax:	proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
Default: —
Context: http
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_path&lt;/code&gt; 用来设置cache的路径以及一些其他配置。levels用来配置目录的层级，以及每个层级的目录命名是由几个16进制的字符表示，
示例:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;proxy_cache_path /root/data/proxy_cache_path levels=1:2 keys_zone=cache:1024m max_size=1024m inactive=15m;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;其中,&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;levels=1:2表示，共有两层目录，第一层目录的名称都是由一个16进制字符表示，第二层目录名称是由两个16进制字符表示&lt;/li&gt;
  &lt;li&gt;keys_zone 用来配置cache的名称以及内存空间大小&lt;/li&gt;
  &lt;li&gt;max_size 用来配置磁盘cache空间的上限&lt;/li&gt;
  &lt;li&gt;inactive 用来配置一个cache多久没有被访问就会失效&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;16-proxy_cache_purge&quot;&gt;16. proxy_cache_purge&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax:	proxy_cache_purge string ...;
Default: —
Context: http, server, location
This directive appeared in version 1.5.7.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_purge&lt;/code&gt; 用来配置cache清除的一些策略, 使用示例:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    location ~ /purge(/.*)
    {
        #设置值允许指定的ip或ip段才可以清除proxy缓存
        allow 127.0.0.1
        allow 192.168.0.0/16;
        deny all;
        proxy_cache_purge cache_name $host$1$is_args$args
    }
    access_log off;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;其中cache_name是通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache&lt;/code&gt;指令设置的cache名称
基于如上配置,
假设一个URL为http://xxx.com/aaa.jpg被proxy cache住了，可以通过访问, http://xxx.com/purge/aaa.jpg来清除该url对应的缓存&lt;/p&gt;

&lt;h4 id=&quot;17-proxy_cache_revalidate&quot;&gt;17. proxy_cache_revalidate&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax:	proxy_cache_revalidate on | off;
Default: proxy_cache_revalidate off;
Context: http, server, location
This directive appeared in version 1.5.7.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_cache_revalidate&lt;/code&gt; 用来配置是否开启过期cache的重新验证, 通过请求头&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;If-Modified-Since&lt;/code&gt; 和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;If-None-Match&lt;/code&gt;来做验证。&lt;/p&gt;

&lt;h3 id=&quot;完整的proxy_cache示例&quot;&gt;完整的proxy_cache示例&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;location /getuserinfo {  
    proxy_pass http://userinfo_upstream;
  
    proxy_cache_revalidate on;   
  
    proxy_cache content; #根keys_zone后的内容对应
    proxy_cache_valid  200 304 301 302 1h;   #哪些状态缓存多长时间
    proxy_cache_methods GET;  # 设置那些http method启用cache, 默认是get和head
    proxy_cache_valid  any 3s;    #其他的缓存多长时间 
    proxy_cache_key $host:$server_port$uri$is_args$args;   #通过key来hash，定义KEY的值 
    proxy_cache_min_uses 1; #只要统一个url,在磁盘文件删除之前，总次数访问到达3次，就开始缓存。  
    proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment; # 如果任何一个参数值不为空，或者不等于0，nginx就不会查找缓存，直接进行代理转发  
}  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_proxy_module.html&quot;&gt;ngx_http_proxy_module&lt;/a&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2019/05/15/nginx-proxy_cache.html</link>
    <guid>http://huyongde.github.io/2019/05/15/nginx-proxy_cache</guid>
    <pubDate>Wed, 15 May 2019 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>nginx error_page指令配置</title>
    <description>&lt;h4 id=&quot;背景介绍&quot;&gt;背景介绍&lt;/h4&gt;
&lt;p&gt;在服务改造优化上线过程中，可能需要用之前的服务对新服务做容错，我们在nginx代理层增加了&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;error_page 403 404 408 500 501 502 503 504  @backend2;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当新服务出现403时，用backend2来容错，backend2正常返回了200状态码，但是端上收到的还是403状态码，
通过查看nginx文章，发现是配置存在问题导致，缺少了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;号，
配置改为&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    error_page 403 404 408 500 501 502 503 504 = @backend2;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这样，端上收到的状态码就是backend2返回的状态码了。&lt;/p&gt;

&lt;h4 id=&quot;error_page-指令详解&quot;&gt;error_page 指令详解&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: error_page code ... [=[response]] uri;
Default:    —
Context:    http, server, location, if in location
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;error_page的作用是当请求返回特定状态码时可以通过uri来容错，code是 http的状态码，可以配置多个code
error_page 可以用在http ,server ,location配置块中，以及location的if配置块中&lt;/p&gt;

&lt;p&gt;示例:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;error_page 404             /404.html;
error_page 500 502 503 504 /50x.html;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;并且error_page支持通过=号来修改返回码，
示例:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;error_page 404 =200 /empty.gif;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;error_page还支持把uri返回的状态码返回给用户
示例:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;error_page 404 = /404.php;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;error_page 允许出现错误时，把请求内部重定向到另一个location, 并且把新location的状态码返回给用户
示例:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;location / {
    error_page 404 = @fallback;
}

location @fallback {
    proxy_pass http://backend;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;error_page 同样支持在出错时对请求做跳转
示例:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;error_page 403      http://example.com/forbidden.html;
error_page 404 =301 http://example.com/notfound.html;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_core_module.html#error_page&quot;&gt;ngx_http_core_module&lt;/a&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2019/05/09/nginx-error_page.html</link>
    <guid>http://huyongde.github.io/2019/05/09/nginx-error_page</guid>
    <pubDate>Thu, 09 May 2019 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>Nginx Proxy_next_upstream</title>
    <description>&lt;h3 id=&quot;介绍&quot;&gt;介绍&lt;/h3&gt;
&lt;p&gt;在使用nginx做代理时，为了容错单点故障，保证服务高可用，可以通过proxy_next_upstream指令来实现某些错误时进行请求重试，
下面详细介绍下proxy_next_upsream相关的几个指令&lt;/p&gt;

&lt;h3 id=&quot;proxy_next_upstream&quot;&gt;proxy_next_upstream&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | http_429 | non_idempotent | off ...;
Default: proxy_next_upstream error timeout;
Context: http, server, location

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ol&gt;
  &lt;li&gt;当通过proxy模块转发请求时，若后端出现&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt; error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | http_429 | non_idempotent&lt;/code&gt;错误时可以重试到upstream配置的下一个后端上，&lt;/li&gt;
  &lt;li&gt;默认是在error 和 timeout时会重试&lt;/li&gt;
  &lt;li&gt;proxy_next_upstream指令用在http, server以及location配置块中&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;配置选项详细介绍:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;error: 和后端建立连接出错，或者从后端读取数据时出错&lt;/li&gt;
  &lt;li&gt;timeout: 和后端交互时发生了超时&lt;/li&gt;
  &lt;li&gt;invalid_header: 后端返回了空的或者非法的数据&lt;/li&gt;
  &lt;li&gt;http_xxx: 后端返回的错误码时xxx, xxx可能为: 500,502,503,504,403,404,429&lt;/li&gt;
  &lt;li&gt;non_idempotent: 默认情况下，对于非幂等请求(POST, LOCK,PATH等) 是不会进行重试的; 但是在增加了这个配置选项时，非幂等的请求也会重试&lt;/li&gt;
  &lt;li&gt;off: 关闭重试&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;proxy_next_upstream_timeout&quot;&gt;proxy_next_upstream_timeout&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_next_upstream_timeout time;
Default: proxy_next_upstream_timeout 0;
Context: http, server, location
This directive appeared in version 1.7.5.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;proxy_next_upstream_timeout用来设定重试时的超时时间，默认值时0，没有超时时间；只在1.7.5以及以后的版本支持&lt;/p&gt;

&lt;h3 id=&quot;proxy_next_upstream_tries&quot;&gt;proxy_next_upstream_tries&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Syntax: proxy_next_upstream_tries number;
Default: proxy_next_upstream_tries 0;
Context: http, server, location
This directive appeared in version 1.7.5.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;proxy_next_upstream_tries 设置可以重试的次数，默认值为0， 表示只要出错，就一直重试下去&lt;/p&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream&quot;&gt;proxy_next_upstream&lt;/a&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2019/05/08/nginx-proxy_next_upstream.html</link>
    <guid>http://huyongde.github.io/2019/05/08/nginx-proxy_next_upstream</guid>
    <pubDate>Wed, 08 May 2019 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>leetcode 24 两两交换链表中的节点</title>
    <description>&lt;h3 id=&quot;题目信息&quot;&gt;题目信息&lt;/h3&gt;

&lt;p&gt;给定一个链表，两两交换其中相邻的节点，并返回交换后的链表。&lt;/p&gt;

&lt;p&gt;示例:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;给定 1-&amp;gt;2-&amp;gt;3-&amp;gt;4, 你应该返回 2-&amp;gt;1-&amp;gt;4-&amp;gt;3.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;要求&quot;&gt;要求&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;你的算法只能使用常数的额外空间。&lt;/li&gt;
  &lt;li&gt;你不能只是单纯的改变节点内部的值，而是需要实际的进行节点交换。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;解法1&quot;&gt;解法1&lt;/h3&gt;
&lt;p&gt;不考虑如上两点要求的话，可以直接两两交换节点的Val&lt;/p&gt;

&lt;h4 id=&quot;代码go&quot;&gt;代码(go)&lt;/h4&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;c&quot;&gt;/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;swapPairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    
     &lt;span class=&quot;n&quot;&gt;直接替换节点val&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;
    
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;解法2&quot;&gt;解法2&lt;/h3&gt;
&lt;p&gt;考虑题目中的两点要求的话，稍微复杂点
除了需要两两交换节点之外，还需要保证整个链表依次顺起来，不成环&lt;/p&gt;

&lt;h4 id=&quot;代码go-1&quot;&gt;代码(go)&lt;/h4&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;swapPairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    
    &lt;span class=&quot;c&quot;&gt;// 替换节点， 交换节点之后，节点的Next也需要做调整， 以便再次能串起来整个list&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;
  
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n1&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
    <link>http://huyongde.github.io/2018/09/11/swapNodesInPairs.html</link>
    <guid>http://huyongde.github.io/2018/09/11/swapNodesInPairs</guid>
    <pubDate>Tue, 11 Sep 2018 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>leetcode 2 两数相加</title>
    <description>&lt;h3 id=&quot;题目信息&quot;&gt;题目信息&lt;/h3&gt;

&lt;p&gt;给定两个非空链表来表示两个非负整数。位数按照逆序方式存储，它们的每个节点只存储单个数字。将两数相加返回一个新的链表。&lt;/p&gt;

&lt;p&gt;你可以假设除了数字 0 之外，这两个数字都不会以零开头。&lt;/p&gt;

&lt;p&gt;示例：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;输入：(2 -&amp;gt; 4 -&amp;gt; 3) + (5 -&amp;gt; 6 -&amp;gt; 4)
输出：7 -&amp;gt; 0 -&amp;gt; 8
原因：342 + 465 = 807
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;解题思路&quot;&gt;解题思路&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;每个链表存储一个数字，位数是逆序存储，从左到右分别是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;个十百千万&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;两个指针从左到右依次遍历两个链表，需要处理链表长度不一致的问题，以及进位问题,&lt;/li&gt;
  &lt;li&gt;跳出循环的前提是没有进位并且两个链表均遍历到最后&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;第一版代码如下go&quot;&gt;第一版代码如下(go)&lt;/h3&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addTwoNumbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l1&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l2&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;addOne&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addOne&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;addOne&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;addOne&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        
        &lt;span class=&quot;c&quot;&gt;// 处理start1 , start2&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; 
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
             &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
       
        &lt;span class=&quot;c&quot;&gt;// 处理current ， 当start1, start2均为空时，跳出循环， 此时需要考虑最后的一次相加的进位问题&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addOne&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                 &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
                 &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addOne&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;       
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;blockquote&gt;
  &lt;p&gt;第一版代码，执行效率不高， 梳理优化后代码如下：&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;第二版代码go&quot;&gt;第二版代码(go)&lt;/h3&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addTwoNumbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l1&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l2&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;addOne&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 
       
        &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addOne&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;addOne&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;addOne&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addOne&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;第二版代码，少了一些判断，执行效率稍高一些&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    <link>http://huyongde.github.io/2018/09/10/addTwoNums.html</link>
    <guid>http://huyongde.github.io/2018/09/10/addTwoNums</guid>
    <pubDate>Mon, 10 Sep 2018 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>leetcode 19. 删除链表的倒数第N个节点</title>
    <description>&lt;h3 id=&quot;题目信息&quot;&gt;题目信息&lt;/h3&gt;

&lt;p&gt;给定一个链表，删除链表的倒数第 n 个节点，并且返回链表的头结点。&lt;/p&gt;

&lt;p&gt;示例：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;给定一个链表: 1-&amp;gt;2-&amp;gt;3-&amp;gt;4-&amp;gt;5, 和 n = 2.

当删除了倒数第二个节点后，链表变为 1-&amp;gt;2-&amp;gt;3-&amp;gt;5.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;说明：&lt;/p&gt;

&lt;p&gt;给定的 n 保证是有效的。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;要求仅遍历一遍链表&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;分析&quot;&gt;分析&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;快慢双指针实现只扫描一趟， 快指针先走n步，然后快慢指针同时走，当快指针到达尾部时，慢指针到第l-n个节点，倒数第n个节点即l-n节点的下一个节点&lt;/li&gt;
  &lt;li&gt;需要处理删除头节点和尾节点的情况&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;代码go&quot;&gt;代码(go)&lt;/h3&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;removeNthFromEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;fast&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;slow&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;slow&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fast&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// 删除头节点&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// 删除尾节点&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;slow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;slow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;执行用时0毫秒，好吧， 看来用go提交代码的比较少，https://leetcode-cn.com/submissions/detail/6872966/&lt;/p&gt;
&lt;/blockquote&gt;
</description>
    <link>http://huyongde.github.io/2018/09/09/deleteNthNodeFromTheListEnd.html</link>
    <guid>http://huyongde.github.io/2018/09/09/deleteNthNodeFromTheListEnd</guid>
    <pubDate>Sun, 09 Sep 2018 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>leetcode 160 两个链表相交，求交点</title>
    <description>&lt;h4 id=&quot;题目信息&quot;&gt;题目信息&lt;/h4&gt;
&lt;p&gt;编写一个程序，找到两个单链表相交的起始节点。&lt;/p&gt;

&lt;p&gt;例如，下面的两个链表：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在节点 c1 开始相交。&lt;/p&gt;

&lt;p&gt;注意：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;如果两个链表没有交点，返回 null.&lt;/li&gt;
  &lt;li&gt;在返回结果后，两个链表仍须保持原有的结构。&lt;/li&gt;
  &lt;li&gt;可假定整个链表结构中没有循环。&lt;/li&gt;
  &lt;li&gt;程序尽量满足 O(n) 时间复杂度，且仅用 O(1) 内存。&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;解法1&quot;&gt;解法1&lt;/h4&gt;
&lt;p&gt;题目拆解为2步&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;判断是否有交点&lt;/li&gt;
  &lt;li&gt;有交点的话，计算出来长度差m，较长链表先走m, 然后一起走，第一个相同的节点即是交点&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;代码c&quot;&gt;代码(c++)&lt;/h4&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Solution&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getIntersectionNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;headA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;headB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmp1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmp2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmp1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;l1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;tmp1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmp2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;l2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;tmp2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//尾节点不一样，肯定不想交&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmp1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tmp1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tmp2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;tmp1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmp1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;         
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;tmp2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmp2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmp1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmp1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;tmp1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;tmp2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;解法2&quot;&gt;解法2&lt;/h4&gt;
&lt;p&gt;分四种情况来解析解法2(先看下代码，再来看分析)&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A B链表长度相同，不想交，直接遍历到最后，p1==p2==NULL 返回NULL&lt;/li&gt;
  &lt;li&gt;A B链表长度相同，相交, 直接遍历到p1==p2!=NULL 返回&lt;/li&gt;
  &lt;li&gt;A B链表长度不同,长度分别为l1, l2，不想交，第一次遍历，比如A链表长，则B链表p2先==NULL, 
p2跳到A链表头开始遍历，此时p1,p2均在遍历A链表，再遍历l1-l2次, p1==NULL, p1跳到B链表头，
此时p1, p2 后面的链表长度相等，重回1，2两个case.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;代码c-1&quot;&gt;代码(c++)&lt;/h4&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Solution&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getIntersectionNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;headA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;headB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headB&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headA&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
    <link>http://huyongde.github.io/2018/09/07/IntersectionTwoLinkedLists.html</link>
    <guid>http://huyongde.github.io/2018/09/07/IntersectionTwoLinkedLists</guid>
    <pubDate>Fri, 07 Sep 2018 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>linux sysstat netstat vmstat 介绍</title>
    <description>&lt;h3 id=&quot;1-sysstat-简介&quot;&gt;1. sysstat 简介&lt;/h3&gt;
&lt;p&gt;sysstat 是linux的一个软件包， 里面包含多个linux 各项性能监控的命令，可以查看监控linux cpu io memory net 等信息&lt;/p&gt;

&lt;h4 id=&quot;11-sysstat-包含的命令列表&quot;&gt;1.1 sysstat 包含的命令列表&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;iostat：统计并报告你的设备的CPU状态和I/O状态数据。&lt;/li&gt;
  &lt;li&gt;mpstat：监控和显示关于每个逻辑CPU的细节信息。&lt;/li&gt;
  &lt;li&gt;pidstat：统计正在运行的进程/任务的CPU、内存等信息, 可以单独查看某个进程的各项信息。&lt;/li&gt;
  &lt;li&gt;tapestat 查看连接到系统的U盘等外接设备的信息&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;sysstat：解释sysstat的各种作用。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;sar：保存和报告不同资源（CPU、内存、输入输出、网络、内核等）的详细信息。&lt;/li&gt;
  &lt;li&gt;sadc：系统活动数据收集器，用于为sar收集后台的数据。&lt;/li&gt;
  &lt;li&gt;sa1：读取和存储sadc的数据文件的二进制数据。&lt;/li&gt;
  &lt;li&gt;sa2：和sar协作，用于总结每日报告。&lt;/li&gt;
  &lt;li&gt;sadf：以不同的格式（CSV或XML）显示sar生成的数据。&lt;/li&gt;
  &lt;li&gt;nfsiostat-sysstat:统计NFS协议的网络文件系统的 I/O状态数据。&lt;/li&gt;
  &lt;li&gt;cifsiostat：统计CIFS协议的网络文件系统的 I/O状态数据。
    &lt;h4 id=&quot;12-mpstat-使用示例&quot;&gt;1.2 mpstat 使用示例&lt;/h4&gt;
  &lt;/li&gt;
&lt;/ul&gt;

</description>
    <link>http://huyongde.github.io/2018/08/02/linux-sysstat.html</link>
    <guid>http://huyongde.github.io/2018/08/02/linux-sysstat</guid>
    <pubDate>Thu, 02 Aug 2018 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>nginx 学习(1) - nginx配置</title>
    <description>&lt;h3 id=&quot;简介&quot;&gt;简介&lt;/h3&gt;
&lt;p&gt;重新学习nginx配置， 简单记录下。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;学习连接： http://openresty.org/cn/ebooks.html&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;0-变量分类&quot;&gt;0. 变量分类：&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;用户自定义变量&lt;/li&gt;
  &lt;li&gt;内建变量&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;1-nginx变量创建赋值作用域&quot;&gt;1. nginx变量创建赋值作用域&lt;/h4&gt;

&lt;p&gt;nginx配置里面的变量是nginx服务启动时创建，   请求到达时进行赋值， 每个请求都有一个变量的副本， 请求内部跳转时变量可以跨location使用。也就是说变量的生命期是和请求绑定的， 可以跨多个location。&lt;/p&gt;

&lt;p&gt;“回到先前对 Nginx 变量值容器的生命期的讨论，我们现在依旧可以说，它们的生命期是与当前请求相关联的。每个请求都有所有变量值容器的独立副本，只不过当前请求既可以是“主请求”，也可以是“子请求”。即便是父子请求之间，同名变量一般也不会相互干扰。”&lt;/p&gt;

&lt;p&gt;摘录来自: agentzh. “agentzh的Nginx教程（2016.07.21版）”。 iBooks.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;echo_location 或者echo_location_async 发起的子请求， 主请求和子请求都会有自己的变量副本， 不会共用。
auth_request 发起的子请求， 主请求和子请求会公用变量副本， 共享变量空间。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;2--内建变量&quot;&gt;2.  内建变量&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;$request_uri 包含参数的url,&lt;/li&gt;
  &lt;li&gt;$uri 不包含参数&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;21-xxxx变量群&quot;&gt;2.1 xxxx变量群&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;$arg_xxxx 表示xxxx参数，  xxxx字符串不区分大小写&lt;/li&gt;
  &lt;li&gt;$http_xxxx, xxxx不区分大小写 用来获取请求头中的xxxx header,&lt;/li&gt;
  &lt;li&gt;$cookie_xxxx ， 不区分大小写 用来获取请求中的cookie xxxx的值&lt;/li&gt;
  &lt;li&gt;$sent_http_xxxx， xxxx不区分大小写 返回头xxxx的值&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;22-存取器&quot;&gt;2.2 存取器&lt;/h4&gt;

&lt;p&gt;设置和读取变量都封装相应的handler&lt;/p&gt;

&lt;h4 id=&quot;3-nginx配置中指令执行顺序&quot;&gt;3 nginx配置中指令执行顺序&lt;/h4&gt;

&lt;p&gt;3.1 nginx对处理请求分为十几个阶段(phase)
指令执行顺序依赖于指令属于哪个阶段， nginx 请求的三个主要阶段，先后顺序是rewrite, access, content&lt;/p&gt;

&lt;p&gt;3.2 一个location中只能使用一个content 阶段的指令， 比如echo ,或者content_by_lua, 两个同时使用时， 只会有一个生效。但是可以在一个location中使用多个echo, 因为多个echo同属于ngx_echo模块。&lt;/p&gt;

&lt;p&gt;3.3 content阶段存在三个垫底的静态资源服务模块ngx_index, ngx_autoindex 以及ngx_static。&lt;/p&gt;

&lt;p&gt;3.4 Nginx处理请求的11个阶段：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;post-read 阶段， 此阶段存在的指令有ngx_realip模块的指令： set_real_ip_from, 以及 real_ip_header, 这两个指令配合使用， 使用示例：
` set_real_ip_from 127.0.0.1; real_ip_header X-Real-ip; `
把来自127.0.0.1的请求的remote_addr 设置为header x-real-ip的值。 后续的阶段或者后端CGI读取的remote_addr都是post-read修改之后的值。 
““注意 只有在x-real-ip header的值是合法ip时， 才会在post_read阶段替换remote_addr””&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;server-rewrite 阶段， ngx_rewrite模块的指令直接在server模块中调用就属于server-rewrite阶段， 比如set, rewrite指令&lt;/li&gt;
  &lt;li&gt;find-config阶段， 此阶段会完成请求和location的配对。&lt;/li&gt;
  &lt;li&gt;rewrite阶段， 请求和某个location配对之后， 便是rewrite阶段， ngx_rewrite模块的指令运行在location中便是在rewrite阶段， 以及ngx_lua的set_by_lua， rewrite_by_lua。&lt;/li&gt;
  &lt;li&gt;post-rewrite阶段， rewrite之后是post-rewrite阶段，来做内部跳转，内部跳转的本质是把请求回退到find-config阶段， 对重写后的请求继续和location进行配对&lt;/li&gt;
  &lt;li&gt;preaccess阶段， post-rewrite 之后便是preaccess 阶段， ngx_limit_req和ngx_limit_zone模块的指令就运行在preaccessJ阶段&lt;/li&gt;
  &lt;li&gt;access 阶段， preaccess之后便是access阶段&lt;/li&gt;
  &lt;li&gt;post-access阶段，satisfy 作用于post-access阶段， satisfy指令用来配合access阶段的控制命令来使用。&lt;/li&gt;
  &lt;li&gt;try-files阶段，此阶段主要是来实现try-files指令，&lt;/li&gt;
  &lt;li&gt;content&lt;/li&gt;
  &lt;li&gt;log&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;try_files 指令接受两个以上任意数量的参数，每个参数都指定了一个 URI. 这里假设配置了 N 个参数，则 Nginx 会在 try-files 阶段，依次把前 N-1 个参数映射为文件系统上的对象（文件或者目录（/结尾会查找目录， 非/结尾会查找文件），然后检查这些对象是否存在。一旦 Nginx 发现某个文件系统对象存在，就会在 try-files 阶段把当前请求的 URI 改写为该对象所对应的参数 URI（但不会包含末尾的斜杠字符，也不会发生 “内部跳转”）。如果前 N-1 个参数所对应的文件系统对象都不存在，try-files 阶段就会立即发起“内部跳转”到最后一个参数（即第 N 个参数）所指定的 URI.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;摘录来自: agentzh. “agentzh的Nginx教程（2016.07.21版）”。 iBooks.&lt;/p&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://openresty.org/download/agentzh-nginx-tutorials-zhcn.html&quot;&gt;agentzh 的 Nginx 教程（版本 2016.07.21）&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;备注&quot;&gt;备注&lt;/h3&gt;
&lt;blockquote&gt;
  &lt;p&gt;文中内容仅供参考， 实际使用请自行测试。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;附上相关看nginx教程时写的nginx conf&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;worker_processes 1;
error_log /Users/huyongde/log/nginx/error.log debug;
pid /Users/huyongde/log/nginx.pid;

events {
    worker_connections 1024;
}

http {
    log_format main  '$remote_addr - $remote_user [$time_local] &quot;$request&quot; '
                      '$status $body_bytes_sent &quot;$http_referer&quot; '
                      '&quot;$http_user_agent&quot; &quot;$http_x_forwarded_for&quot;';
    access_log /Users/huyongde/log/nginx/access.log main;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay  on;
    keepalive_timeout 10;
    types_hash_max_size 2048;

    server {
        listen 8666;
        server_name default;

        set $addr $remote_addr;   ##set指令属于ngx_rewrite模块 运行于server-rewrite阶段, 在post-read阶段之后

        set_real_ip_from 127.0.0.1;    ##这两个指令属于ngx_realio模块运行在post-read阶段，post阶段是nginx处理请求的最早阶段
        real_ip_header Real-Ip;

        location /satisfy {
            satisfy any;
            deny all;
            access_by_lua &quot;ngx.exit(ngx.OK)&quot;;
            echo &quot;satisfy all&quot;;
        }

        location /foo {
            rewrite ^ /bar;
            rewrite ^ /baz;
        }

        location /bar {
            echo &quot;bar&quot;;
        }

        location /baz {
            echo &quot;baz&quot;;
        }



        location /test {
            echo &quot;addr $addr&quot;;
            echo &quot;remote_addr : $remote_addr&quot;;
            set $b &quot;$a , test&quot;;
            echo &quot;b: $b&quot;;
        }
        set $a &quot;Hello from Server_rewrite&quot;; ## 运行在server_rewrite 阶段， 所以早于所有location内的指令

        location /test2 {
            echo &quot;args : $args&quot;;
        }

    }

    server {
        listen 8070;
        server_name default;
        location /static2 {
            root /Users/huyongde/Desktop/html;
            try_files /foo =404;  # 在root目录下查找foo文件， 找不到就返回404 , 404可以修改为任一http状态码
        }
        location /static3 {
            root /Users/huyongde/Desktop/html;
            try_files /bar/ =404; # 在root目录下查找bar目录， 若不存在则返回404 , 若存在bar目录， 则请求uri会被设置为/bar匹配/bar location, 测试时直接返回了301， response header location 是/bar?$args
#bar 目录存在时请求 127.0.0.1:8070/static3?a=1&amp;amp;b=2 返回如下：
#&amp;lt; HTTP/1.1 301 Moved Permanently
#&amp;lt; Server: openresty/1.11.2.5
#&amp;lt; Date: Sun, 05 Nov 2017 14:05:07 GMT
#&amp;lt; Content-Type: text/html
#&amp;lt; Content-Length: 191
#&amp;lt; Location: http://127.0.0.1:8070/bar/?a=1&amp;amp;b=2
#&amp;lt; Connection: keep-alive
#&amp;lt;
#&amp;lt;html&amp;gt;
#&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;301 Moved Permanently&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;
#&amp;lt;body bgcolor=&quot;white&quot;&amp;gt;
#&amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;301 Moved Permanently&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt;
#&amp;lt;hr&amp;gt;&amp;lt;center&amp;gt;openresty/1.11.2.5&amp;lt;/center&amp;gt;
#&amp;lt;/body&amp;gt;
#&amp;lt;/html&amp;gt;

        }

        location /static {
            set $orig_uri $uri;
            set $orig_request_uri $request_uri;
            root /Users/huyongde/Desktop/html;
            try_files /index.html /index.htm /not_found; ### 在根目录下查找index.html文件以及index.htm文件，若找到，则把当前请求的uri改写为匹配的try_files参数中的URI， 若前n-1个都不匹配则会跳转到第n个参数指定的uri.
            #echo &quot;Orig_uri: $orig_uri, now uri: $uri&quot;;
            #echo &quot;Orig_request_uri: $orig_request_uri, now uri: $request_uri&quot;;
            #index index.html index.htm; ### index 指令就是执行了内部跳转
        }

        location /not_found {
            echo &quot;not found&quot;;
        }
        location /index.html {
            set $a 10000;
            echo &quot;a : $a&quot;;
        }
        location /phase {
            # rewrite phase
            set $age 100;
            rewrite_by_lua &quot;ngx.var.age = ngx.var.age + 10&quot;;
            # access phase
            allow 127.0.0.1;
            deny all;
            access_by_lua &quot;ngx.var.age = ngx.var.age + 12&quot;;

            #content phase
            echo &quot;Age : $age&quot;;

        }
        location /lua {
            content_by_lua '
                if ngx.var.arg_name == nil then
                    ngx.say(&quot;param missing&quot;)
                else
                    ngx.say(&quot;name:[&quot;, ngx.var.arg_name, &quot;]&quot; )
                end
            ';
        }
        location /auth {
            allow 127.0.0.1;
            deny all;
            echo &quot;auth example&quot;;
            access_by_lua '
                if ngx.var.remote_addr == &quot;127.0.0.1&quot;  then
                    ngx.say(&quot;from access_by_lua&quot;)
                else
                    ngx.exit(403)
                end
            ';
        }

        location /main {  ## 测试主请求  子请求
            set $var main;
            echo_location /child1;
            echo_location /child2;
            echo &quot;main : var $var&quot;;
        }

        location /child1 {
            echo &quot;child1&quot;;
            set $var child1_var;
            echo &quot;child1 var : $var&quot;;
        }
        location /child2 {
            echo &quot;child2&quot;;
            set $var &quot;child2_var&quot;;
            echo &quot;child2 var: $var&quot;;
        }

        location /proxy {
            set $args &quot;a=1&amp;amp;b=2&quot;;
            echo_before_body &quot;before proxy&quot;;
            # 不能直接使用echo指令， echo指令和proxy_pass指令同属content阶段，只会执行proxy_pass, 下面的echo_after_body同理
            #
            proxy_pass http://127.0.0.1:8666/test2; ## 参数会自动带到新的请求上
            echo_after_body &quot;after proxy&quot;;
        }

        location /test {
            set $foo &quot;Hello nginx &quot; ;
            set $a &quot;$foo  $foo ${foo}xxxx&quot;;
            echo &quot;test echo :$a&quot;;
            echo  &quot;uri = $uri&quot;;
            echo  &quot;request_uri: $request_uri&quot;;
            echo &quot;params a arg_a: $arg_a&quot;;
            echo &quot;params a arg_A: $arg_A&quot;;
            echo &quot;header test: $http_test&quot;;
            echo &quot;header Test: $http_Test&quot;;
            echo &quot;cookie test: $cookie_test&quot;;
            echo &quot;cookie Test: $cookie_Test&quot;;
            set $sent_http_test &quot;res test header&quot;;

            set $orig_test $arg_test;
            echo &quot;origin param test: $orig_test&quot;;
            set $args &quot;test=confset&quot;;
            echo &quot;param test : $arg_test&quot;;
        }

        location /foo {
            set $a  &quot;foo&quot;;
            #echo_exec /bar;
            rewrite ^ /bar;
        }
        location /bar {
            echo &quot;a=${a}&quot;;
        }

    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
    <link>http://huyongde.github.io/2017/11/05/nginx-conf.html</link>
    <guid>http://huyongde.github.io/2017/11/05/nginx-conf</guid>
    <pubDate>Sun, 05 Nov 2017 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>微信小程序开发总结</title>
    <description>&lt;h3 id=&quot;简介&quot;&gt;简介&lt;/h3&gt;

&lt;p&gt;学习微信小程序开发中遇到问题，总结一下。&lt;/p&gt;

&lt;h3 id=&quot;模板消息遇到的问题&quot;&gt;模板消息遇到的问题&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;区分ID和template_id, id是所有小程序都可以使用的，是”模板库”里面的ID, template_id 是我的模板中的ID， template_id 是发模板消息时需要使用的。&lt;/li&gt;
  &lt;li&gt;请求POST接口时， request body需要是json字符串， 比如PHP语言，需要这样设置request body &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data))&lt;/code&gt; data是由请求参数组成的数组， 比如：/cgi-bin/wxopen/template/library/list 这个接口，要是request_body 格式不对， 会返回 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system error hint:xxxx&lt;/code&gt;的错误信息, post请求的抓包数据如下：&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;POST /cgi-bin/wxopen/template/library/list?access_token=ZAnYXewHQFzsAlOwGsAgB4AIAhHnW9y-2B7EghTvvdIokI8JZtosZ-MieDNwzYdM_Sc4lNq4EJ9AOkcRTZ0PXOHg2MQlD5w7B4V__4LChI1_1qJPTlyXz-V1oplIjuK_UIVcABAAOB HTTP/1.1
Host: api.weixin.qq.com
Accept: */*
Content-Length: 22
Content-Type: application/x-www-form-urlencoded

{&quot;offset&quot;:0,&quot;count&quot;:3}HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: application/json; encoding=utf-8
Date: Sat, 16 Sep 2017 15:19:33 GMT
Content-Length: 183

{&quot;errcode&quot;:0,&quot;errmsg&quot;:&quot;ok&quot;,&quot;list&quot;:[{&quot;id&quot;:&quot;AT0002&quot;,&quot;title&quot;:&quot;..................&quot;},{&quot;id&quot;:&quot;AT0003&quot;,&quot;title&quot;:&quot;..................&quot;},{&quot;id&quot;:&quot;AT0004&quot;,&quot;title&quot;:&quot;............&quot;}],&quot;total_count&quot;:880}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;鉴权服务搭建&quot;&gt;鉴权服务搭建，&lt;/h3&gt;
&lt;p&gt;github: https://github.com/tencentyun/wafer-session-server&lt;/p&gt;

&lt;p&gt;会话服务来实现cookie的功能， 需要创建存储appid以及用户session信息的表，并导入appid和secret记录，
并且需要&lt;strong&gt;&lt;em&gt;检查system/db/db.ini文件中db访问的配置&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;鉴权服务和小程序后端服务的nginx配置&quot;&gt;鉴权服务和小程序后端服务的nginx配置&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;server {
    listen 80;
    rewrite_log on;
    access_log  /Users/huyongde/Desktop/wxapplet/wafer-demo/logs/access.log ;
    error_log  /Users/huyongde/Desktop/wxapplet/wafer-demo/logs/error.log  debug;
    root /Users/huyongde/Desktop/wxapplet;

    location ^~ /wafer-demo {
        root /Users/huyongde/Desktop/wxapplet/wafer-demo;
        rewrite ^/wafer-demo/(.*)$ /index.php/$1 break;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        include        fastcgi.conf;
    }
    location ^~ /wafer-session-server {
        rewrite ^/wafer-session-server(.*)$ /wafer-session-server/index.php/$1 break;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        include        fastcgi.conf;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;对应的代码目录是：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;▾ wxapplet/
  ▸ demo/
  ▸ server/
  ▸ wafer-client-demo/
  ▸ wafer-demo/
  ▸ wafer-session-server/
 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中wafer-demo对应的是&lt;a href=&quot;https://github.com/tencentyun/wafer-php-server-demo&quot;&gt;wafer-php-server-demo&lt;/a&gt;的代码&lt;/p&gt;

&lt;p&gt;wafer-session-server是会话服务的代码&lt;/p&gt;

&lt;p&gt;### wafer-demo(小程序后端) 代码修改：&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;application/config/routes.php&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;文件最后一行加一个路由设置&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$route['wafer-demo/(.*)'] = '$1';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;配合nginx的conf来实现ci框架的自动路由&lt;/p&gt;

&lt;p&gt;### 配置sdk.config, 配置小程序后端用到的各项服务：
 wafer-demo 目录下创建&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdk.config&lt;/code&gt;文件，并且修改&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wafer-demo/wafer-demo/install_qcloud_sdk.php&lt;/code&gt;文件中的sdkConfig变量 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$sdkConfig='./sdk.config&lt;/code&gt;
 sdk.config文件内容为：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; {
    &quot;serverHost&quot;: &quot;127.0.0.1&quot;,
    &quot;authServerUrl&quot;: &quot;http://127.0.0.1/wafer-session-server/&quot;,
    &quot;tunnelServerUrl&quot;: &quot;https://ws.qcloud.com&quot;,
    &quot;tunnelSignatureKey&quot;: &quot;key&quot;,
    &quot;networkTimeout&quot;: 6000
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;其中authServerUrl 是会话的鉴权服务
 tunnelServerUrl是websockets的信道服务， 使用腾讯云提供的就可以&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;如上改动之后的小程序相关代码， 记录在了 https://github.com/huyongde/wx 的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minapp&lt;/code&gt;中,server 中的代码是小程序API相关的， wafer开头的目录是搭建小程序官方demo使用的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;#### 问题&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;FastCGI sent in stderr: “Primary script unknown” while reading response header from upstream， 解决方法：用普通账户运行php-fpm， 不用root账户， 也不用sudo php-fpm&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;小程序信道服务&quot;&gt;小程序信道服务&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wafer-demo/vendor/qcloud/weapp-sdk/lib/Tunnel/TunnelService.php&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;修改此处签名教研部分的代码后才跑通信道测试。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;如上内容仅供参考，如有问题欢迎交流。&lt;/p&gt;
&lt;/blockquote&gt;
</description>
    <link>http://huyongde.github.io/2017/09/23/wxapp-dev.html</link>
    <guid>http://huyongde.github.io/2017/09/23/wxapp-dev</guid>
    <pubDate>Sat, 23 Sep 2017 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>go 源码安装</title>
    <description>&lt;h4 id=&quot;源码下载&quot;&gt;源码下载&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;https://golang.org/dl/ 可以下载golang各个版本的源码&lt;/li&gt;
  &lt;li&gt;https://github.com/golang/go 也可从github上clone源码&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;安装&quot;&gt;安装&lt;/h4&gt;

&lt;p&gt;问题1：&lt;/p&gt;

&lt;p&gt;从源码src目录下运行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./all.bash&lt;/code&gt;， 出现如下错误：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;##### Building Go bootstrap tool.
cmd/dist
ERROR: Cannot find /home/campus/go1.4/bin/go.
Set $GOROOT_BOOTSTRAP to a working Go tree &amp;gt;= Go 1.4.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;问题原因： 编译安装1.5以及以上版本的go时，需要依赖go1.4版本&lt;/p&gt;

&lt;p&gt;解决方法： 下载1.4的源码，编译安装，并且设置GOROOT, GOBIN, PATH, 以及GOROOT_BOOTSTRAP环境变量。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
export GOROOT=&quot;/home/campus/yongdehu/go&quot;
export GOBIN=$GOROOT/bin
export PATH=$GOBIN:$PATH
export GOROOT_BOOTSTRAP=$GOROOT

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;问题2： 
解决问题1之后，再运行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./make.bash&lt;/code&gt; 时， 提示&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;go tool dist: FAILED: not a Git repo; must put a VERSION file in $GOROOT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;问题原因： 从github clone的go 源码目录下没有VERSION文件。&lt;/p&gt;

&lt;p&gt;解决方法： 直接 从官网下载最新的golang源代码进行安装&lt;/p&gt;

&lt;p&gt;安装完成之后， 运行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./go version &lt;/code&gt;
输出如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;go version go1.8.3 linux/amd64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;把GOROOT和PATH更新为最新安装的目录&lt;/p&gt;

&lt;p&gt;安装完成。&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2017/08/23/golang-sourcecode-install.html</link>
    <guid>http://huyongde.github.io/2017/08/23/golang-sourcecode-install</guid>
    <pubDate>Wed, 23 Aug 2017 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>浮点数剖析 (PHP)</title>
    <description>&lt;h4 id=&quot;php面试中-经常会被问到的一个问题&quot;&gt;PHP面试中, 经常会被问到的一个问题&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;?php
    $f = 0.58;
    var_dump(intval($f * 100)); 
?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上面输出的结果是57， 而不是58， 为什么呢， 因为 &lt;strong&gt;你看似有穷的小数, 在计算机的二进制表示里却是无穷的&lt;/strong&gt;(鸟哥的原话)，0.58用二进制后， 重新计算出来的值是：0.57999999999999996， 所以乘以100之后，去整数部分，就是57了。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;代码中的intval改为floor后，输出的结果也是57&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;名字解释&quot;&gt;名字解释&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;BC是Binary Calculator的缩写, 二进制计算器&lt;/li&gt;
  &lt;li&gt;Sign 符号&lt;/li&gt;
  &lt;li&gt;Exponent 指数&lt;/li&gt;
  &lt;li&gt;Fraction 小数&lt;/li&gt;
  &lt;li&gt;IEEE 英语：Institute of Electrical and Electronics Engineers 电子技术与电子工程师协会，简称为IEEE。 IEEE is the world’s largest technical professional organization dedicated to advancing technology for the benefit of humanity. Below, you can find IEEE’s mission and vision statements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;参考文章鸟哥的两篇文章外加ieee-754&quot;&gt;参考文章，鸟哥的两篇文章外加IEEE 754&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.laruence.com/2013/03/26/2884.html&quot;&gt;PHP 浮点数的一个常见问题的解答&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.laruence.com/2011/12/19/2399.html&quot;&gt;关于PHP浮点数你应该知道的&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/IEEE_754&quot;&gt;IEEE 754 / IEEE二进制浮点数算术标准&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IEEE 754 全称为，IEEE二进制浮点数算术标准， 
此标准中，规定了浮点数二进制表示的规范：&lt;/p&gt;

&lt;p&gt;浮点数二进制表示包括三部分，&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;符号位， 用1个字节来表示&lt;/li&gt;
  &lt;li&gt;指数位，&lt;/li&gt;
  &lt;li&gt;有效数字&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;如：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;单精度浮点数共32位(bit)，1bit的符号位，8bit指数位，23bit有效数字&lt;/li&gt;
  &lt;li&gt;双精度浮点数共64位(bit)，1bit的符号位，11bit指数位，52bit有效数字&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;浮点数表示为二进制的计算方式是: &lt;a href=&quot;http://blog.163.com/yql_bl/blog/static/847851692008112013117685/&quot;&gt;浮点数二进制表示学习笔记&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;整数部分除以2取余，然后再用所得的商除以2取余，一直到商为0，并且逆序排列所得的余数; 小数部分乘以2取整数部分，然后再用新的小数部分乘以二，取整数，一直到新的小数部分为0， 或者达到了要求的精度为止, 并且顺序排列所得的整数部分。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;浮点数转化为二进制的例子&quot;&gt;浮点数转化为二进制的例子&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;10.625转化为二进制&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;整数部分10， 对2求余， 商继续对2求余，直到商为0， 再逆序排列每一步得到的余数&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;计算&lt;/th&gt;
      &lt;th&gt;余数&lt;/th&gt;
      &lt;th&gt;商&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;10/2&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5/2&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2/2&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1/2&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;10的二进制表示为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1010&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;小数部分0.625， 乘以2， 取整数部分，新的小数部分继续乘以2， 直到新的小数部分为0或者达到一定精度，再顺序排列每一步得到整数部分。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;计算&lt;/th&gt;
      &lt;th&gt;整数部分&lt;/th&gt;
      &lt;th&gt;小数部分&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0.625 * 2 = 1.25&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.25&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.25 * 2 = 0.5&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.5 * 2 = 1&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;0.625的二进制表示为101&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;0.58的二进制表示
比如要求的精度是用53位来表示这个小数，可以得到如下表格：&lt;/li&gt;
&lt;/ol&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;计算&lt;/th&gt;
      &lt;th&gt;整数部分&lt;/th&gt;
      &lt;th&gt;小数部分&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0.58 * 2 = 1.16&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.16&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.16 * 2 = 0.32&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.32&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.32 * 2 = 0.64&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.64&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.64 * 2 = 1.28&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.28&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.28 * 2 = 0.56&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.56&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.56 * 2 = 1.12&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.12&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.12 * 2 = 0.24&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.24&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.24 * 2 = 0.48&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.48&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.48 * 2 = 0.96&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.96&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.96 * 2 = 1.92&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.92&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.92 * 2 = 1.84&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.84&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.84 * 2 = 1.68&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.68&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.68 * 2 = 1.36&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.36&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.36 * 2 = 0.72&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.72&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.72 * 2 = 1.44&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.44&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.44 * 2 = 0.88&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.88&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.88 * 2 = 1.76&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.76&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.76 * 2 = 1.52&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.52&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.52 * 2 = 1.04&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.04&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.04 * 2 = 0.08&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.08&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.08 * 2 = 0.16&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.16&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.16 * 2 = 0.32&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.32&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.32 * 2 = 0.64&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.64&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.64 * 2 = 1.28&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.28&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.28 * 2 = 0.56&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.56&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.56 * 2 = 1.12&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.12&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.12 * 2 = 0.24&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.24&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.24 * 2 = 0.48&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.48&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.48 * 2 = 0.96&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.96&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.96 * 2 = 1.92&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.92&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.92 * 2 = 1.84&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.84&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.84 * 2 = 1.68&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.68&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.68 * 2 = 1.36&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.36&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.36 * 2 = 0.72&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.72&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.72 * 2 = 1.44&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.44&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.44 * 2 = 0.88&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.88&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.88 * 2 = 1.76&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.76&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.76 * 2 = 1.52&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.52&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.52 * 2 = 1.04&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.04&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.04 * 2 = 0.08&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.08&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.08 * 2 = 0.16&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.16&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.16 * 2 = 0.32&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.32&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.32 * 2 = 0.64&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.64&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.64 * 2 = 1.28&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.28&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.28 * 2 = 0.56&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.56&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.56 * 2 = 1.12&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.12&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.12 * 2 = 0.24&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.24&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.24 * 2 = 0.48&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.48&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.48 * 2 = 0.96&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0.96&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.96 * 2 = 1.92&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.92&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.92 * 2 = 1.84&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.84&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.84 * 2 = 1.68&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.68&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0.68 * 2 = 1.36&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0.36&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;0.58 的二进制为： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10010100011110101110000101000111101011100001010001111&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;如上表格是通过如下 程序简单生成的：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.58&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;52&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; * 2 &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;intval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$b&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$str&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;= &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tmp&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; | &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$int&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; | &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;浮点数比较&quot;&gt;浮点数比较&lt;/h4&gt;
&lt;p&gt;看似两个相等的浮点数，其实进行比较时， 可能不想等了。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$f = 0.58;
$f2 = 1 - 0.42;
var_dump($f == $f2);
printf(&quot;%.21f \n&quot;, $f);
printf(&quot;%.21f \n&quot;, $f2);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如上代码大家觉着会输出什么呢？ 其实输出的结果是：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bool(false)
0.579999999999999960032
0.580000000000000071054
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;所以在做浮点数比较的时候，要谨慎处理, 或者round四舍五入之后再比较。&lt;/p&gt;

&lt;h4 id=&quot;精度输出&quot;&gt;精度输出&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;for($i=1;$i&amp;lt;=55; $i++) {
    printf(&quot;%d %.{$i}f\n&quot;, $i, 0.58);
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如上代码，输出结果为：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1 0.6
2 0.58
3 0.580
4 0.5800
5 0.58000
6 0.580000
7 0.5800000
8 0.58000000
9 0.580000000
10 0.5800000000
11 0.58000000000
12 0.580000000000
13 0.5800000000000
14 0.58000000000000
15 0.580000000000000
16 0.5800000000000000
17 0.57999999999999996
18 0.579999999999999960
19 0.5799999999999999600
20 0.57999999999999996003
21 0.579999999999999960032
22 0.5799999999999999600320
23 0.57999999999999996003197
24 0.579999999999999960031971
25 0.5799999999999999600319711
26 0.57999999999999996003197111
27 0.579999999999999960031971113
28 0.5799999999999999600319711135
29 0.57999999999999996003197111349
30 0.579999999999999960031971113494
31 0.5799999999999999600319711134944
32 0.57999999999999996003197111349436
33 0.579999999999999960031971113494365
34 0.5799999999999999600319711134943645
35 0.57999999999999996003197111349436454
36 0.579999999999999960031971113494364545
37 0.5799999999999999600319711134943645447
38 0.57999999999999996003197111349436454475
39 0.579999999999999960031971113494364544749
40 0.5799999999999999600319711134943645447493
41 0.57999999999999996003197111349436454474926
42 0.579999999999999960031971113494364544749260
43 0.5799999999999999600319711134943645447492599
44 0.57999999999999996003197111349436454474925995
45 0.579999999999999960031971113494364544749259949
46 0.5799999999999999600319711134943645447492599487
47 0.57999999999999996003197111349436454474925994873
48 0.579999999999999960031971113494364544749259948730
49 0.5799999999999999600319711134943645447492599487305
50 0.57999999999999996003197111349436454474925994873047
51 0.579999999999999960031971113494364544749259948730469
52 0.5799999999999999600319711134943645447492599487304688
53 0.57999999999999996003197111349436454474925994873046875
PHP Notice:  printf(): Requested precision of 54 digits was truncated to PHP maximum of 53 digits in /data/cweb/2870000/campus_debug/website/v1/campus.imqq.cn/yongdehu_dev_api/protected/test.php on line3
54 0.57999999999999996003197111349436454474925994873046875
PHP Notice:  printf(): Requested precision of 55 digits was truncated to PHP maximum of 53 digits in /data/cweb/2870000/campus_debug/website/v1/campus.imqq.cn/yongdehu_dev_api/protected/test.php on line3
55 0.57999999999999996003197111349436454474925994873046875
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;i为54 和 55 时， PHP给了提示,并且输出结果和i=53时是一样的，最大支持小数点后53个小数。&lt;/li&gt;
  &lt;li&gt;i 为1时，输出的是0.58四舍五入为只有一位小数的值，&lt;/li&gt;
  &lt;li&gt;i 为17时才出现了0.57， 说明从16位之前2位之后的所有位四舍五入之后都是0.58&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;printf在输出浮点数时，会根据设定的位数来做四舍五入。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;代码仅仅演示使用，文章内容不保证没有问题， 仅供参考。 欢迎交流指正。&lt;/p&gt;
&lt;/blockquote&gt;
</description>
    <link>http://huyongde.github.io/2017/08/18/php-float.html</link>
    <guid>http://huyongde.github.io/2017/08/18/php-float</guid>
    <pubDate>Fri, 18 Aug 2017 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>静态变量(static) 和 全局变量(global)</title>
    <description>&lt;h4 id=&quot;参考&quot;&gt;参考&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://php.net/manual/zh/language.variables.scope.php&quot;&gt;php变量范围&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;静态变量&quot;&gt;静态变量&lt;/h4&gt;

&lt;blockquote&gt;
  &lt;p&gt;静态变量仅在&lt;strong&gt;局部函数域&lt;/strong&gt;中存在，但当程序执行离开此作用域时，其值并不丢失。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$a = 10;

function test ($a) {
   static $a = 1;
   echo $a . &quot;\n&quot;;
   $a ++ ;
}
test($a);
test($a);
test($a);
echo $a . &quot;\n&quot; ;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如上PHP脚本的输出应该为&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1
2
3
10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;函数内的静态变量不是存储在函数的栈空间中， 而是存储在了堆空间中，无论函数调用多少次，静态变量仅初始化一次， 并且每次对静态变量的操作的都会累积。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;静态变量也提供了一种处理递归函数的方法。递归函数是一种调用自己的函数。写递归函数时要小心，因为可能会无穷递归下去。必须确保有充分的方法来中止递归。&lt;/p&gt;

&lt;p&gt;以下这个简单的函数递归计数到 10，使用静态变量 $count 来判断何时停止&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
function test2() {
    static $a = 0;
    $a++;
    echo $a;
    if ($a &amp;gt;10) {
        echo $a . &quot;end \n&quot;;
        return;
    }
    test2();
}
test2();

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;递归了10次， 一共调用test2函数11次。&lt;/p&gt;

&lt;h4 id=&quot;全局变量&quot;&gt;全局变量&lt;/h4&gt;

&lt;p&gt;函数中使用全局变量时，需要用global关键字对全局变量进行声明，声明之后就可以在函数内使用全局变量了。如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$a = 1;
$b = 2;

function Sum()
{
    global $a, $b;

    $b = $a + $b;
}

Sum();
echo $b;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;还可以使用$GLOBALS超全局变量来访问全局变量。
如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$a = 1;
$b = 2;

function Sum()
{
    $GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
}

Sum();
echo $b;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;超全局变量 $GLOBALS 是一个关联数组，每一个变量为一个元素，键名对应变量名，值对应变量的内容。&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2017/08/17/php-global-static.html</link>
    <guid>http://huyongde.github.io/2017/08/17/php-global-static</guid>
    <pubDate>Thu, 17 Aug 2017 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>PHP in_array 源码学习， 以及in_array和isset效率比较</title>
    <description>&lt;h3 id=&quot;背景知识&quot;&gt;背景知识&lt;/h3&gt;

&lt;p&gt;工作中通过xhprof分析接口性能，在xhprof产生的结果中发现如下一条&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Function Name&lt;/td&gt;
      &lt;td&gt;Calls&lt;/td&gt;
      &lt;td&gt;Calls%&lt;/td&gt;
      &lt;td&gt;Incl. Wall Time(microsec)&lt;/td&gt;
      &lt;td&gt;IWall%&lt;/td&gt;
      &lt;td&gt;Excl. Wall Time(microsec)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;in_array&lt;/td&gt;
      &lt;td&gt;6,115&lt;/td&gt;
      &lt;td&gt;36.9%&lt;/td&gt;
      &lt;td&gt;1,857,818&lt;/td&gt;
      &lt;td&gt;43.6%&lt;/td&gt;
      &lt;td&gt;1,857,818&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;调用了6K次的in_array耗时接近2秒， 数组里面大概有1W个元素， 这个耗时明显是不能接受的。就想办法改成了通过isset来实现in_array的功能。&lt;/p&gt;

&lt;p&gt;通过简单的脚本测试，发现isset确实比in_array快， 这也很好理解， isset是O(1)的时间复杂度， in_array则是O(n)。&lt;/p&gt;

&lt;h3 id=&quot;in_array-源码梳理&quot;&gt;in_array 源码梳理&lt;/h3&gt;

&lt;p&gt;为了弄清楚in_array的实现，梳理了下in_array的源码。&lt;/p&gt;

&lt;h5 id=&quot;函数实现入口在php-srcextstandardarrayc如下&quot;&gt;函数实现入口在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;php-src/ext/standard/array.c&lt;/code&gt;如下：&lt;/h5&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/* proto bool in_array(mixed needle, array haystack [, bool strict])
   Checks if the given value exists in the array */&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;PHP_FUNCTION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;php_search_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;INTERNAL_FUNCTION_PARAM_PASSTHRU&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h5 id=&quot;主要实现逻辑都在php_search_array中-代码如下&quot;&gt;主要实现逻辑都在php_search_array中， 代码如下：&lt;/h5&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior)
 * 0 = return boolean  in_array时 behavior为0
 * 1 = return key array_search 时behavior为1
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;inline&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;php_search_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;INTERNAL_FUNCTION_PARAMETERS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;behavior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;zval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;                &lt;span class=&quot;cm&quot;&gt;/* value to check for */&lt;/span&gt;
         &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;                &lt;span class=&quot;cm&quot;&gt;/* array to check in */&lt;/span&gt;
         &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;cm&quot;&gt;/* pointer to array entry */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;zend_ulong&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;zend_string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;zend_bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;strict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;cm&quot;&gt;/* strict comparison or not */&lt;/span&gt;


    &lt;span class=&quot;cm&quot;&gt;/*
     * php7 使用了fast parameter parsing Api 来解析参数
     * ZEND_PARSE_PARAMETERS_START() 的两个参数分别为最少参数数和最多参数数。
     * Z_PARAM_ZVAL() 则将参数视为zval，Z_PARAM_ARRAY() 将参数视为数组。
     * Z_PARAM_OPTIONAL 则表示后面的参数为可选参数
     * Z_PARAM_BOOL 表示参数是布尔型
     * add by huyongde 参考：http://www.php-internals.com/book/?p=chapt11/11-02-01-zend-parse-parameters
     */&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;ZEND_PARSE_PARAMETERS_START&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/*  */&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Z_PARAM_ZVAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Z_PARAM_ARRAY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Z_PARAM_OPTIONAL&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Z_PARAM_BOOL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ZEND_PARSE_PARAMETERS_END&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ZEND_HASH_FOREACH_KEY_VAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Z_ARRVAL_P&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// 对数组进行遍历&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ZVAL_DEREF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fast_is_identical_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;behavior&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;RETURN_TRUE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;RETVAL_STR_COPY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;RETVAL_LONG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ZEND_HASH_FOREACH_END&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 数组遍历结束&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Z_TYPE_P&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IS_LONG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ZEND_HASH_FOREACH_KEY_VAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Z_ARRVAL_P&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fast_equal_check_long&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;behavior&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;RETURN_TRUE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;RETVAL_STR_COPY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;RETVAL_LONG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ZEND_HASH_FOREACH_END&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Z_TYPE_P&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IS_STRING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
            &lt;span class=&quot;n&quot;&gt;ZEND_HASH_FOREACH_KEY_VAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Z_ARRVAL_P&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fast_equal_check_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;behavior&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;RETURN_TRUE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;RETVAL_STR_COPY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;RETVAL_LONG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ZEND_HASH_FOREACH_END&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ZEND_HASH_FOREACH_KEY_VAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Z_ARRVAL_P&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fast_equal_check_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;behavior&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;RETURN_TRUE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;RETVAL_STR_COPY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;RETVAL_LONG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ZEND_HASH_FOREACH_END&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;RETURN_FALSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;php_search_array-中一些主要的宏或者函数介绍如下&quot;&gt;php_search_array 中一些主要的宏或者函数介绍如下&lt;/h5&gt;
&lt;ul&gt;
  &lt;li&gt;ZEND_HASH_FOREACH_KEY_VAL 和 ZEND_HASH_FOREACH_END 两个宏 定义在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;php-src/Zend/zend_hash.h&lt;/code&gt; 中， 用来实现遍历数组中的元素&lt;/li&gt;
  &lt;li&gt;fast_is_identical_function 定义在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;php-src/Zend/zend_operators.h&lt;/code&gt; 中， 用来弱类型比较两个对象是否相等&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;fast_equal_check_[string&lt;/td&gt;
          &lt;td&gt;long&lt;/td&gt;
          &lt;td&gt;function] 三个函数也定义在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;php-src/Zend/zend_operators.h&lt;/code&gt; 中用来比较字符串是否相等， 整型是否相等，函数是否相等&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;从源码可以看到in_array时间复杂度确实是O(n)。&lt;/p&gt;

&lt;h4 id=&quot;isset-和-in_array性能比较&quot;&gt;isset 和 in_array性能比较&lt;/h4&gt;

&lt;p&gt;简单的测试代码如下：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;testInArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$rand&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;in_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$rand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;testIsset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$rand&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$rand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;array_push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$arr2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$arr2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;microtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;testInArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$start2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;microtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;testIsset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;microtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;in_array time: &quot;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$start2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;isset time: &quot;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$start2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;测试结果输出结果如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;in_array time: 717.60702133179
isset time: 44.092893600464
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;时间单位毫秒， 差别还是挺明显的。&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2017/07/19/php-in_array&&isset-sourcecode.html</link>
    <guid>http://huyongde.github.io/2017/07/19/php-in_array&&isset-sourcecode</guid>
    <pubDate>Wed, 19 Jul 2017 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>登录git发评论专用页</title>
    <description>&lt;h3 id=&quot;登录git发评论专用页点击下面的登录按钮登录git&quot;&gt;登录git发评论专用页,点击下面的登录按钮，登录git&lt;/h3&gt;
</description>
    <link>http://huyongde.github.io/2017/05/24/login-git.html</link>
    <guid>http://huyongde.github.io/2017/05/24/login-git</guid>
    <pubDate>Wed, 24 May 2017 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>php 扩展信息查看</title>
    <description>&lt;h3 id=&quot;查看php扩展的相关信息&quot;&gt;查看php扩展的相关信息&lt;/h3&gt;
</description>
    <link>http://huyongde.github.io/2017/04/21/php-extension-info.html</link>
    <guid>http://huyongde.github.io/2017/04/21/php-extension-info</guid>
    <pubDate>Fri, 21 Apr 2017 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>Yii 框架missingAction函数xss漏洞分析解决</title>
    <description>&lt;h3 id=&quot;yii-missingaction-xss漏洞&quot;&gt;Yii missingAction xss漏洞&lt;/h3&gt;
&lt;p&gt;missingAction 是Yii框架controller层用来处理用户请求的action不存在的情况的方法， 在CController.php中实现。&lt;/p&gt;

&lt;p&gt;core/web/CController.php中，missingAction代码如下， &lt;a href=&quot;https://github.com/yiisoft/yii/blob/1.1.17/framework/web/CController.php&quot;&gt;CController.php全部代码&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cd&quot;&gt;/**
 * Handles the request whose action is not recognized.
 * This method is invoked when the controller cannot find the requested action.
 * The default implementation simply throws an exception.
 * @param string $actionID the missing action name
 * @throws CHttpException whenever this method is invoked
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;missingAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$actionID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CHttpException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;404&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Yii&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'yii'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'The system is unable to find the requested action &quot;{action}&quot;.'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'{action}'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$actionID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;defaultAction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$actionID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)));&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;actionID 变量直接返回可能会导致xss攻击
比如下列请求，&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://yourhost/api/albumPic/getClassPhotoList&amp;lt;a hREF=feed:javascript&amp;amp;colon;prompt(972840)&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;直接用actionID变量组成异常信息抛出到前端的话，可能会带来xss攻击， 可以对actionid做一下处理，会避免xss攻击
 代码修改为：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CHttpException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;404&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Yii&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'yii'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'The system is unable to find the requested action &quot;{action}&quot;.'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'{action}'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;htmlspecialchars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$actionID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;defaultAction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$actionID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))));&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;php-web-安全总结&quot;&gt;php web 安全总结&lt;/h3&gt;
&lt;p&gt;可能存在的攻击类型&lt;/p&gt;
&lt;h4 id=&quot;1-xss-cross-site-script--跨站脚本攻击&quot;&gt;1. xss (cross site script ) 跨站脚本攻击&lt;/h4&gt;
&lt;p&gt;预防策略： 对用户输入使用函数strip_tags(), htmlspecialchars()以及htmlentities()进行过滤。&lt;/p&gt;

&lt;h4 id=&quot;2-mysql数据注入&quot;&gt;2. mysql数据注入&lt;/h4&gt;
&lt;p&gt;预防策略：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;addslashes() 对字符串进行特殊字符的处理，&lt;/li&gt;
  &lt;li&gt;mysql_escape_string(), mysql_real_escape_string()对sql语句进行特殊字符转义处理， mysql_real_escape_string转义sql字符串中特殊字符时还会考虑到当前链接的字符集， php 4.3版本以后引入的。&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;3-csrf-cross-site-request-forgery--跨站请求伪造&quot;&gt;3. csrf (cross site request forgery ) 跨站请求伪造&lt;/h4&gt;
&lt;h4 id=&quot;4-拒绝服务攻击dos以及分布式拒绝服务攻击ddos&quot;&gt;4. 拒绝服务攻击(dos)以及分布式拒绝服务攻击(ddos)&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;dos: denial of service  拒绝服务攻击&lt;/li&gt;
  &lt;li&gt;ddos distributed denial-of-service 分布式拒绝服务攻击&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2017/01/18/php-Yii-xss.html</link>
    <guid>http://huyongde.github.io/2017/01/18/php-Yii-xss</guid>
    <pubDate>Wed, 18 Jan 2017 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>php 扩展开发--- 开发PHP第一个扩展</title>
    <description>&lt;h3 id=&quot;开发php第一个扩展&quot;&gt;开发PHP第一个扩展&lt;/h3&gt;
&lt;h4 id=&quot;1-使用ext_skel-生成扩展的骨架&quot;&gt;1 使用ext_skel 生成扩展的骨架&lt;/h4&gt;
&lt;p&gt;下载php源码，源码的ext目录下有个shell脚本&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ext_skel&lt;/code&gt;, 此脚本是用来生成PHP扩展框架的， 使用示例：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd ./ext/ ;
./ext_skel --extname=myext // 生成名为myext的扩展
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;生成之后目录结构如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ tree .
.
|-- CREDITS
|-- EXPERIMENTAL
|-- config.m4
|-- config.w32
|-- myext.c
|-- myext.php
|-- php_myext.h
`-- tests
    `-- 001.phpt

1 directory, 8 files

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;2-修改配置文件configm4&quot;&gt;2 修改配置文件config.m4&lt;/h4&gt;
&lt;p&gt;需要把配置文件中相关的注释去掉，去掉注释的地方如下:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dnl PHP_ARG_WITH(myext, for myext support,
dnl Make sure that the comment is aligned:
dnl [  --with-myext             Include myext support])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;需要把第一行和第三行的dnl去掉，
config.m4 是unix平台开发扩展的配置文件，config.w32是windows下开发扩展用到的配置文件。&lt;/p&gt;

&lt;h4 id=&quot;3-动态编译扩展&quot;&gt;3 动态编译扩展&lt;/h4&gt;
&lt;p&gt;依次执行如下命令：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;phpize&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./configure --with-php-config=/your_path/php-config&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make install&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;执行完make之后，在当前目录的modules目录下会生成一个myext.so的文件,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make install&lt;/code&gt; 负责把myext.so复制到php的extension_dir(php.ini中配置的php扩展文件所在目录)目录，&lt;/p&gt;

&lt;p&gt;通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;php -i | grep extension&lt;/code&gt; 可以查看相关的配置， 我的开发机运行结果如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ php -i | grep extension
extension_dir =&amp;gt; /usr/local/php/lib/extensions/ =&amp;gt; /usr/local/php/lib/extensions/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make install&lt;/code&gt; 这步可能会遇到没有权限的问题，需要切换到root后再执行，或者直接自己手动copy过去&lt;/p&gt;

&lt;p&gt;到此第一个php扩展开发完成，为了验证扩展是否可以正确使用可以进行如下操作
` php -r “var_dump(confirm_myext_compiled(‘test’));” `&lt;/p&gt;

&lt;p&gt;正常情况下会返回如下结果:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string(106) &quot;Congratulations! You have successfully modified ext/myext/config.m4. Module test is now compiled into PHP.&quot;&lt;/code&gt;&lt;/p&gt;

&lt;h4 id=&quot;4-在扩展中编写自己的函数&quot;&gt;4 在扩展中编写自己的函数&lt;/h4&gt;
&lt;p&gt;在myext扩展中增加函数hello_world,需要如下三个操作：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;php_myext.h 中添加: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PHP_FUNCTION(hello_world);&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;myext.c 的myext_functions数组中添加&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt; PHP_FE(hello_world, NULL)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;myext.c 中进行hello_world函数体的编写,代码如下：&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;PHP_FUNCTION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hello_world&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg_len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zend_parse_parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ZEND_NUM_ARGS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TSRMLS_CC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;s&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg_len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FAILURE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hello world %s&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RETURN_STRINGL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;完成如上三步之后，进行编译三连发： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./configure --with-php-config=/yourpath/php-config; make; make install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;PHP 中验证hello_world函数：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ php -r &quot;var_dump(hello_world('test'));&quot;
string(16) &quot;hello world test&quot;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;至此基本完成了开发PHP扩展的基本流程， happy coding!&lt;/p&gt;

&lt;h4 id=&quot;5-遇到的问题&quot;&gt;5 遇到的问题&lt;/h4&gt;

&lt;p&gt;添加hello_world函数时，遇到了 ‘zif_hello_world’ undeclared here (not in a function)
类似的错误，这个错误是因为没有再php_myext.h中添加响应函数声明导致，php_myext.h中添加：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PHP_FUNCTION(hello_world);&lt;/code&gt; 后问题解决&lt;/p&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://521-wf.com/archives/227.html&quot;&gt;php扩展编译的两种方式&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2016/12/17/php-extension-first-extension.html</link>
    <guid>http://huyongde.github.io/2016/12/17/php-extension-first-extension</guid>
    <pubDate>Sat, 17 Dec 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>php 扩展开发--- config.m4解读</title>
    <description>&lt;h3 id=&quot;1-ext_skel-扩展骨架生成的-configm4解读&quot;&gt;1. ext_skel 扩展骨架生成的 config.m4解读&lt;/h3&gt;

&lt;h4 id=&quot;configm4-实例&quot;&gt;config.m4 实例&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dnl $Id$
dnl config.m4 for extension example
PHP_ARG_WITH(example, for example support,
[  --with-example[=FILE]       Include example support. File is the optional path to example-config])
PHP_ARG_ENABLE(example-debug, whether to enable debugging support in example,
[  --enable-example-debug        example: Enable debugging support in example], no, no)
PHP_ARG_WITH(example-extra, for extra libraries for example,
[  --with-example-extra=DIR      example: Location of extra libraries for example], no, no)

dnl 检测扩展是否已启用
if test &quot;$PHP_EXAMPLE&quot; != &quot;no&quot;; then
  
  dnl 检测 example-config。首先尝试所给出的路径，然后在 $PATH 中寻找
  AC_MSG_CHECKING([for example-config])
  EXAMPLE_CONFIG=&quot;example-config&quot;
  if test &quot;$PHP_EXAMPLE&quot; != &quot;yes&quot;; then
    EXAMPLE_PATH=$PHP_EXAMPLE
  else
    EXAMPLE_PATH=`$php_shtool path $EXAMPLE_CONFIG`
  fi
  
  dnl 如果找到可用的 example-config，就使用它
  if test -f &quot;$EXAMPLE_PATH&quot; &amp;amp;&amp;amp; test -x &quot;$EXAMPLE_PATH&quot; &amp;amp;&amp;amp; $EXAMPLE_PATH --version &amp;gt; /dev/null 2&amp;gt;&amp;amp;1; then
    AC_MSG_RESULT([$EXAMPLE_PATH])
    EXAMPLE_LIB_NAME=`$EXAMPLE_PATH --libname`
    EXAMPLE_INCDIRS=`$EXAMPLE_PATH --incdirs`
    EXAMPLE_LIBS=`$EXAMPLE_PATH --libs`
    
    dnl 检测扩展库是否工作正常
    PHP_CHECK_LIBRARY($EXAMPLE_LIB_NAME, example_critical_function,
    [
      dnl 添加所需的 include 目录
      PHP_EVAL_INCLINE($EXAMPLE_INCDIRS)
      dnl 添加所需的扩展库及扩展库所在目录
      PHP_EVAL_LIBLINE($EXAMPLE_LIBS, EXAMPLE_SHARED_LIBADD)
    ],[
      dnl 打印错误信息，并推出./configure
      AC_MSG_ERROR([example library not found. Check config.log for more information.])
    ],[$EXAMPLE_LIBS]
    )
  else
    dnl 没有可用的 example-config，跳出
    AC_MSG_RESULT([not found])
    AC_MSG_ERROR([Please check your example installation.])
  fi
  
  dnl 检测是否启用调试
  if test &quot;$PHP_EXAMPLE_DEBUG&quot; != &quot;no&quot;; then
    dnl 是，则设置 C 语言宏指令
    AC_DEFINE(USE_EXAMPLE_DEBUG,1,[Include debugging support in example])
  fi
  
  dnl 检测额外的支持
  if test &quot;$PHP_EXAMPLE_EXTRA&quot; != &quot;no&quot;; then
    if test &quot;$PHP_EXAMPLE_EXTRA&quot; == &quot;yes&quot;; then
      AC_MSG_ERROR([You must specify a path when using --with-example-extra])
    fi
    
    PHP_CHECK_LIBRARY(example-extra, example_critical_extra_function,
    [
      dnl 添加所需路径
      PHP_ADD_INCLUDE($PHP_EXAMPLE_EXTRA/include)
      PHP_ADD_LIBRARY_WITH_PATH(example-extra, $PHP_EXAMPLE_EXTRA/lib, EXAMPLE_SHARED_LIBADD)
      AC_DEFINE(HAVE_EXAMPLEEXTRALIB,1,[Whether example-extra support is present and requested])
      EXAMPLE_SOURCES=&quot;$EXAMPLE_SOURCES example_extra.c&quot;
    ],[
      AC_MSG_ERROR([example-extra lib not found. See config.log for more information.])
    ],[-L$PHP_EXAMPLE_EXTRA/lib]
    )
  fi
  
  dnl 最后，将扩展及其所需文件等信息传给构建系统
  PHP_NEW_EXTENSION(example, example.c $EXAMPLE_SOURCES, $ext_shared)
  PHP_SUBST(EXAMPLE_SHARED_LIBADD)
fi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;简单解读&quot;&gt;简单解读&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;dnl 表示注释&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;PHP_ARG_WITH&lt;/td&gt;
          &lt;td&gt;PHP_ARG_ENABLE： 有三个参数，第一个参数是我们的扩展名(注意不用加引号)，第二个参数是当我们运行./configure脚本时显示的内容，最后一个参数则是我们在调用./configure –help时显示的帮助信息&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;AC_MSG_*: AC 是autoconf的缩写，* 可以为：checking, result, notice, error, failure, warn。AC_MSG_* 均为autoconf宏。
    &lt;ul&gt;
      &lt;li&gt;AC_MSG_CHECKING()，一个 autoconf 宏，输出一行标准的如 “checking for …” 的信息&lt;/li&gt;
      &lt;li&gt;AC_MSG_* 每个宏的具体用处可以参考&lt;a href=&quot;https://www.gnu.org/software/autoconf/manual/autoconf-2.60/autoconf.html&quot;&gt;autoconf printing messages&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;PHP_ADD_INCLUDE: PHP_ADD_INCLUDE() 和 PHP_ADD_LIBRARY_WITH_PATH() 用于构建额外功能所需的头文件路径、库文件路径和库标志&lt;/li&gt;
  &lt;li&gt;PHP_CHECK_LIBRARY，这是 PHP 构建系统提供的一个宏，包装了 autoconf 的 AC_CHECK_LIB() 函数， 用来检查扩展库是否正常工作。PHP_CHECK_LIBRARY()尝试编译、链接和执行程序，在第一个参数指定的库中调用由第二个参数指定的符号，使用第五个参数给出的字符串作为额外的链接选项。如果尝试成功了，则运行第三个参数所给出的脚本。此脚本从 example-config 所提供的原始的选项字符串中取出头文件路径、库文件路径和库名称，告诉 PHP 构建系统。如果尝试失败，脚本则运行第四个参数中的脚本。此时调用 AC_MSG_ERROR() 来中断程序执行&lt;/li&gt;
  &lt;li&gt;AC_DEFINE: 设置C语言宏指令&lt;/li&gt;
  &lt;li&gt;PHP_SUBST() 来启用扩展的共享构建&lt;/li&gt;
  &lt;li&gt;PHP_NEW_EXTENSION: 告诉构建系统去构建扩展本身和被其用到的文件, 第一个参数是扩展的名称，也就是config.m4所在的目录名称, 第二个参数是做为扩展的一部分的所有源文件的列表。参见 PHP_ADD_BUILD_DIR() 以获取将在子目录中源文件添加到构建过程的相关信息。第三个参数总是 $ext_shared， 当为了 –with-example[=FILE] 而调用 PHP_ARG_WITH()时，由 configure 决定参数的值。第四个参数指定一个“SAPI 类”，仅用于专门需要 CGI 或 CLI SAPI 的扩展。其他情况下应留空。第五个参数指定了构建时要加入 CFLAGS 的标志列表。第六个参数是一个布尔值，为 “yes” 时会强迫整个扩展使用 $CXX 代替 $CC 来构建。第三个以后的所有参数都是可选的&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://php.net/manual/zh/internals2.buildsys.configunix.php&quot;&gt;PHP骇客 之 与UNIX构建系统交互: config.m4&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/autoconf/manual/autoconf-2.60/autoconf.html&quot;&gt;autoconf manual&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2016/12/15/php-extension-config.m4.html</link>
    <guid>http://huyongde.github.io/2016/12/15/php-extension-config.m4</guid>
    <pubDate>Thu, 15 Dec 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>yii table schema cache and query result cache</title>
    <description>&lt;h3 id=&quot;简介&quot;&gt;简介&lt;/h3&gt;

&lt;p&gt;本文主要介绍YII框架性能优化相关的两个方法：数据库表元信息cache以及数据库查询结果cache。&lt;/p&gt;

&lt;h3 id=&quot;yii-db-schema-cache-相关&quot;&gt;Yii db schema cache 相关：&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Yii框架可能比较慢的原因: 
 It will do a show columns query, then a show create tablequery, then finally it will query the database for the actual data. Those first two queries are so Yii knows the schema of your user table. If the round trip time from your application server to your database server is 100ms (if it’s really this slow, you should do something about it), then those two queries to get the schema will add a minimum of 200ms to your application response time. It will do this for every single request that populates your User model. Depending on how your application is written, it might even do that multiple times in a single request.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;翻译过来大概意思是：Yii框架在真正执行sql之前需要执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;show columns from xxx;show create table xxx&lt;/code&gt;, 相当于额外增加了两次数据库操作，为了节省这两次数据库操作的时间，引入了数据库表schema的cache, 常用cache有memcache,redis等&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;cache key 的构成：类CDbSchema(framework/db/schema/CDbSchema.php)中的getTable方法中会利用到schema cache来获取数据库表的metadata即schema， 其中包括了如何生成缓存table metadata 的key等代码。&lt;a href=&quot;https://github.com/yiisoft/yii/blob/1.1.17/framework/db/schema/CDbSchema.php#L72&quot;&gt;源码链接&lt;/a&gt;       关键代码：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$key='yii:dbschema'.$this-&amp;gt;_connection-&amp;gt;connectionString.':'.$this-&amp;gt;_connection-&amp;gt;username.':'.$name;&lt;/code&gt;, 以字符串的形式把表的schema信息存储在cache中。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;yii-db-query-result-cache--相关&quot;&gt;Yii db query result cache  相关&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;缓存数据库查询结果到cache的方法的&lt;a href=&quot;https://github.com/yiisoft/yii/blob/1.1.17/framework/caching/CCache.php#L173&quot;&gt;源码&lt;/a&gt;， 是CCache类的set成员函数，其中有处理dependency的逻辑，函数代码如下：&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; public function set($id,$value,$expire=0,$dependency=null)
    {
        Yii::trace('Saving &quot;'.$id.'&quot; to cache','system.caching.'.get_class($this));
        if ($dependency !== null &amp;amp;&amp;amp; $this-&amp;gt;serializer !== false)
            $dependency-&amp;gt;evaluateDependency();
        if ($this-&amp;gt;serializer === null)
            $value = serialize(array($value,$dependency));
        elseif ($this-&amp;gt;serializer !== false)
            $value = call_user_func($this-&amp;gt;serializer[0], array($value,$dependency));
        return $this-&amp;gt;setValue($this-&amp;gt;generateUniqueKey($id), $value, $expire);
    }

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;从代码可以看到cache下来的数据包括了dependency的信息，&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;从cache中获取query result时的&lt;a href=&quot;https://github.com/yiisoft/yii/blob/1.1.17/framework/caching/CCache.php#L102&quot;&gt;源码&lt;/a&gt;, 其中会把cache中的dependency的内容去掉，再返回给调用者，详细代码如下:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public function get($id)
    {
        $value = $this-&amp;gt;getValue($this-&amp;gt;generateUniqueKey($id));
        if($value===false || $this-&amp;gt;serializer===false)
            return $value;
        if($this-&amp;gt;serializer===null)
            $value=unserialize($value);
        else
            $value=call_user_func($this-&amp;gt;serializer[1], $value);
        if(is_array($value) &amp;amp;&amp;amp; (!$value[1] instanceof ICacheDependency || !$value[1]-&amp;gt;getHasChanged()))
        {
            Yii::trace('Serving &quot;'.$id.'&quot; from cache','system.caching.'.get_class($this));
            return $value[0];
        }
        else
            return false;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;query result cache 查询和写入的入口在CDbCommand的queryInternal函数，&lt;a href=&quot;https://github.com/yiisoft/yii/blob/1.1.17/framework/db/CDbCommand.php#L470&quot;&gt;源码&lt;/a&gt;,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其中调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cache-&amp;gt;get&lt;/code&gt;的部分核心代码如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$cacheKey='yii:dbquery'.':'.$method.':'.$this-&amp;gt;_connection-&amp;gt;connectionString.':'.$this-&amp;gt;_connection-&amp;gt;username;
            $cacheKey.=':'.$this-&amp;gt;getText().':'.serialize(array_merge($this-&amp;gt;_paramLog,$params));
            if(($result=$cache-&amp;gt;get($cacheKey))!==false)
            {
                Yii::trace('Query result found in cache','system.db.CDbCommand');
                return $result[0];
            }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cache-&amp;gt;set&lt;/code&gt;的核心代码如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if(isset($cache,$cacheKey))
    $cache-&amp;gt;set($cacheKey,array($result),$this-&amp;gt;_connection-&amp;gt;queryCachingDuration, $this-&amp;gt;_connection-&amp;gt;queryCachingDependency);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;对于query result cache依赖的dependency, 相关的类有：CCacheDependency类，类中有计算dependency是否变化的函数getHasChanged此函数需要依赖函数generateDependentData(), &lt;strong&gt;当新生成的dependency的属性值于cache中缓存下来的值发生变化时&lt;/strong&gt;，则认为此query result cache已经失效， 需要重新从数据库获取最新数据. &lt;a href=&quot;https://github.com/yiisoft/yii/blob/1.1.17/framework/caching/dependencies/CCacheDependency.php#L67&quot;&gt;CCacheDependency的源码&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;query result cache 其实是把一个复杂的sql查询，依赖于一个相对简单的sql查询，缓存到cache中，每次都去检查简单的sql结果是否发生变化，没发生变化的话就认为复杂的sql查询结果也没发生变化。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;数据库表schema-cache以及query-result-cache-的相关配置如下&quot;&gt;数据库表schema cache以及query result cache 的相关配置如下:&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    'components' =&amp;gt; array(
        'db' =&amp;gt; array(       
            'schemaCachingDuration'=&amp;gt;3600, // 缓存有效期 3600秒
            'queryCachingDuration'=&amp;gt;3600,
            //默认使用cache组件，显示的申明使用redis组件来缓存schemaData和query result
            'schemaCacheID'=&amp;gt;'redis',
            'queryCacheID'=&amp;gt;'redis', // redis组件也需要在components中单独配置
        ),
    )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;query-result-cache-示例&quot;&gt;query result cache 示例&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    $sql = '执行比较耗时的sql';
    $dependency = new CDbCacheDependency('比较简单的会影响到比较耗时sql的sql');
    $rows = Yii::app()-&amp;gt;db-&amp;gt;cache(1000, $dependency)-&amp;gt;createCommand($sql)-&amp;gt;queryAll();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.yiiframework.com/doc/api/1.1/&quot;&gt;Yii 官网文档&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/23466159/the-schema-caching-in-yii&quot;&gt;stack overflow &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2016/10/19/yii-study-cache.html</link>
    <guid>http://huyongde.github.io/2016/10/19/yii-study-cache</guid>
    <pubDate>Wed, 19 Oct 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>sublime text 3  扩展包安装以及遇到的问题</title>
    <description>&lt;h3 id=&quot;简介&quot;&gt;简介&lt;/h3&gt;
&lt;p&gt;最近在用sublime text3, 通过package control 可以安装的扩展包真的太多了，很强大
但是在安装的时候遇到了一些问题&lt;/p&gt;

&lt;h3 id=&quot;vcs-gutter&quot;&gt;VCS gutter&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;具体介绍和安装可以去&lt;a href=&quot;https://github.com/bradsokol/VcsGutter&quot;&gt;git官网&lt;/a&gt; , 
  这个sublime 3 的插件主要是来判断某一行代码是否被修改删除或者添加过， 支持的版本控制系统(vcs: version control system )有git, svn, hg等.&lt;/li&gt;
  &lt;li&gt;VCS Gutter对于git来说就相当于git Gutter, 安装VCS Gutter之后，就可以remove 掉 Git Gutter了.&lt;/li&gt;
  &lt;li&gt;安装完成之后，需要修改用户配置文件，修改后的VCS Gutter 用户配置文件如下:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
{
	&quot;vcs_paths&quot;: {
	        &quot;diff&quot;: &quot;C:\\Users\\Administrator\\.babun\\cygwin\\bin\\diff.exe&quot;,
	        &quot;git&quot;: &quot;C:\\Users\\Administrator\\.babun\\cygwin\\bin\\git.exe&quot;,
	        &quot;hg&quot;: &quot;&quot;,
	        &quot;svn&quot;: &quot;C:\\Program Files\\TortoiseSVN\\bin\\svn.exe&quot;,
	},
	 &quot;live_mode&quot;: false,
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;主要是配置各个版本控制系统的可执行命令的路径，以及diff路径，如上是我的配置文件，windows系统上面安装了babun(windows系统上的linux shell软件)， 可执行文件都配置的是babun相关的路径。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;sublime-linter&quot;&gt;Sublime Linter&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;具体的安装参考&lt;a href=&quot;http://www.sublimelinter.com/en/latest/installation.html&quot;&gt;官网&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;sublime linter 是sublime 用来做代码检查用的，可以发现代码存在的语法等的问题， **安装了Sublime Linter之后，需要为每一种语言单独安装语言特有的linter **
比如php语言需要安装&lt;a href=&quot;https://github.com/SublimeLinter/SublimeLinter-php&quot;&gt;SublimeLinter-PHP&lt;/a&gt;, SublimeLinter-PHP这个插件是通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt; php -l &lt;/code&gt;来实现语法检查的。&lt;/li&gt;
  &lt;li&gt;安装完sublime linter 以及sublimeLinter-php之后，出现php语法错误后，sublime编辑器会给如下提示:
&lt;img src=&quot;/image/sublimeLinter.png&quot; alt=&quot;错误提示&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;其中，右上方提示了具体的错误信息，左下方红点表示错误发生的位置， 红点上方的绿色的加好是Vcs Gutter显示的代码基于当前版本所做的修改。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;sublime linter 安装完成之后，可以再安装，sublimeLinter-phpcs以及sublimeLinter-phpmd, 分别是php的code sniffer以及mess detector
    &lt;ul&gt;
      &lt;li&gt;phpcs 根据PHP代码标准(PSR: PHP Standards Recommendations )来检查代码是否符合标准, 详细的各种php代码标准参考&lt;a href=&quot;http://www.php-fig.org/psr/&quot;&gt;psr&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;phpmd 是根据某些规则来检查你的代码是否符合规则，比如说函数和变量的命名是否合理，if else 使用是否合理，定义的变量是否使用等的规则，详情请参考&lt;a href=&quot;https://phpmd.org/rules/index.html&quot;&gt;phpmd.org&lt;/a&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;package control 安装了sublimeLinter-phpcs 以及sublimeLinter-phpmd之后，需要用pear来安装它们所以依赖的php相关的可执行文件，phpcs以及phpmd， 安装命令如下:
    &lt;ul&gt;
      &lt;li&gt;安装phpmd:&lt;/li&gt;
    &lt;/ul&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  pear channel-discover pear.phpmd.org
  pear channel-discover pear.pdepend.org
  pear install --alldeps phpmd/PHP_PMD
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ul&gt;
      &lt;li&gt;安装phpcs： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pear install --alldeps PHP_CodeSniffer&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;phpcs和phpmd搞定之后，好多不符合规范的提示，如下图，闹心啊!!!
&lt;img src=&quot;/image/phpcs-phpmd.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;太多格式不符合要求了。闹心啊闹心，最后把phpcs直接禁止了，只留了phpmd的一些规则检查，相关的linter配置如下（是sublimeLinter的配置，phpcs和phpmd貌似没有单独的配置）:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &quot;linters&quot;: {
            &quot;php&quot;: {
                &quot;@disable&quot;: false,
                &quot;args&quot;: [],
                &quot;excludes&quot;: []
            },
            &quot;phpcs&quot;: {
                &quot;@disable&quot;: true,
                &quot;args&quot;: [],
                &quot;cmd&quot;: &quot;C:\\pear\\phpcs.bat&quot;,
                &quot;excludes&quot;: [],
                &quot;standard&quot;: &quot;PSR1&quot;
            },
            &quot;phpmd&quot;: {
                &quot;@disable&quot;: false,
                &quot;args&quot;: [],
                &quot;cmd&quot;: &quot;C:\\pear\\phpmd.bat&quot;,
                &quot;excludes&quot;: [],
                &quot;rulesets&quot;: &quot;naming,unusedcode&quot;
            }
        },
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;sublimecodeintel&quot;&gt;SublimeCodeIntel&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;此插件是sublime 用来做代码补全的, codeIntel 全称code intelligence 代码智能的意思&lt;/li&gt;
  &lt;li&gt;安装参考&lt;a href=&quot;https://github.com/SublimeCodeIntel/SublimeCodeIntel&quot;&gt;SublimeCodeIntel&lt;/a&gt;, 安装完成之后，做了如下配置：&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
    &quot;PHP&quot;: {
        &quot;php&quot;: &quot;/cygdrive/c/wamp64/bin/php/php7.0.0/php&quot;,
        &quot;phpExtraPaths&quot;: [],
        &quot;phpConfigFile&quot;: &quot;/cygdrive/c/wamp64/bin/php/php7.0.0/php.ini&quot;
    },
    &quot;JavaScript&quot;: {
        &quot;javascriptExtraPaths&quot;: []
    },
    &quot;Python&quot;: {
        &quot;python&quot;: &quot;C:\\Users\\Administrator\\.babun\\cygwin\\bin\\python&quot;,
        &quot;pythonExtraPaths&quot;: []
    },
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;问题&quot;&gt;问题&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;安装完成SublimeCodeIntel后，使用时不成功，通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C+~&lt;/code&gt; 调出来命名窗口，发现 &lt;strong&gt;OSError: [WinError 6] 句柄无效&lt;/strong&gt; 的错误。 这个问题google了下，stackoverflow上面有个相关的解决方案 &lt;a href=&quot;http://stackoverflow.com/questions/3028786/how-can-i-fix-error-6-the-handle-is-invalid-with-pyserial&quot;&gt;链接&lt;/a&gt;，说是python安装的版本不对.
我的系统是win7 64, 需要安装64位的python, 下载了&lt;a href=&quot;https://www.python.org/ftp/python/2.7.12/python-2.7.12rc1.amd64.msi&quot;&gt;安装包&lt;/a&gt;
重新安装后，重新设置了环境变量PATH， 再次进行js编程时就可以自动提示并且补全了。&lt;/li&gt;
  &lt;li&gt;安装了多个插件之后，sublime经常性卡顿，尝试设置了下gitgutter的user配置， 添加配置&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
    &quot;non_blocking&quot; : &quot;true&quot;,
    &quot;live_mode&quot; : &quot;false&quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;修改之后稍微有些改观，可能还有其他的插件导致这个问题。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;后续有问题继续更新&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;配置前端开发的扩展包&quot;&gt;配置前端开发的扩展包&lt;/h3&gt;

&lt;h4 id=&quot;参考&quot;&gt;&lt;a href=&quot;http://www.cnblogs.com/hykun/p/sublimeText3.html&quot;&gt;参考&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;上篇博文中包括了emmet,SublimeCodeIntel, SideBar等的扩展插件。&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2016/06/24/sublime-text3-package.html</link>
    <guid>http://huyongde.github.io/2016/06/24/sublime-text3-package</guid>
    <pubDate>Fri, 24 Jun 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>php output buffering 配置和相关函数学习</title>
    <description>&lt;h3 id=&quot;简介&quot;&gt;简介&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;output buffering&lt;/code&gt; 简称ob, 是输出缓冲区， 通过php配置以及output control （输出控制函数）来控制php的输出， 输出控制函数不会作用于setcookie以及header两个输出标头的函数， 只
会作用于类似与echo类的函数.&lt;/p&gt;

&lt;h3 id=&quot;php-缓冲区分类&quot;&gt;php 缓冲区分类&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;用户缓冲区 通过ob_xxx函数来操作， ob_start创建一个用户缓冲区&lt;/li&gt;
  &lt;li&gt;php默认缓冲区&lt;/li&gt;
  &lt;li&gt;sapi缓冲区&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;output-buffering-相关的php-配置&quot;&gt;output buffering 相关的php 配置&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;output_buffering boolean/integer 该选项设置为 On 时，将在所有的脚本中使用输出控制。如果要限制输出缓冲区的最大值，可将该选项设定为指定的最大字节数（例如 output_buffering=4096）。从PHP 4.3.5 版开始，该选项在 PHP-CLI 下总是为 Off。 设置为On时，相当于每次执行完echo类的输出后，自动执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ob_flush()&lt;/code&gt;函数.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;implicit_flush boolean 默认为 FALSE。如将该选项改为 TRUE，PHP 将使输出层，在每段信息块输出后，自动刷新。这等同于在每次使用 print、echo 等函数或每个 HTML 块之后，调用 PHP 中的 flush() 函数。 不在web环境中使用 PHP 时，打开这个选项对程序执行的性能有严重的影响，通常只推荐在调试时使用。在 CLI SAPI 的执行模式下，该标记默认为 TRUE。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;output_handler string 该选项可将脚本所有的输出，重定向到一个函数。例如，将 output_handler 设置为 mb_output_handler() 时，字符的编码将被修改为指定的编码。设置的任何处理函数，将自动的处理输出缓冲。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;不能同时使用 mb_output_handler() 和 ob_iconv_handler()，也不能同时使用 ob_gzhandler() 和 zlib.output_compression&lt;/strong&gt;
&lt;strong&gt;只有内置函数可以使用此指令。对于用户定义的函数，使用 ob_start()&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;output-buffering-相关的函数&quot;&gt;output buffering 相关的函数&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;flush — 刷新输出缓冲&lt;/li&gt;
  &lt;li&gt;ob_clean — 清空（擦掉）输出缓冲区&lt;/li&gt;
  &lt;li&gt;ob_end_clean — 清空（擦除）缓冲区并关闭输出缓冲&lt;/li&gt;
  &lt;li&gt;ob_end_flush — 冲刷出（送出）输出缓冲区内容并关闭缓冲&lt;/li&gt;
  &lt;li&gt;ob_flush — 冲刷出（送出）输出缓冲区中的内容&lt;/li&gt;
  &lt;li&gt;ob_get_clean — 得到当前缓冲区的内容并删除当前输出缓。&lt;/li&gt;
  &lt;li&gt;ob_get_contents — 返回输出缓冲区的内容&lt;/li&gt;
  &lt;li&gt;ob_get_flush — 刷出（送出）缓冲区内容，以字符串形式返回内容，并关闭输出缓冲区。&lt;/li&gt;
  &lt;li&gt;ob_get_length — 返回输出缓冲区内容的长度&lt;/li&gt;
  &lt;li&gt;ob_get_level — 返回输出缓冲机制的嵌套级别&lt;/li&gt;
  &lt;li&gt;ob_get_status — 得到所有输出缓冲区的状态&lt;/li&gt;
  &lt;li&gt;ob_gzhandler — 在ob_start中使用的用来压缩输出缓冲区中内容的回调函数。ob_start callback function to gzip output buffer&lt;/li&gt;
  &lt;li&gt;ob_implicit_flush — 打开/关闭绝对刷送&lt;/li&gt;
  &lt;li&gt;ob_list_handlers — 列出所有使用中的输出处理程序。&lt;/li&gt;
  &lt;li&gt;ob_start — 打开输出控制缓冲&lt;/li&gt;
  &lt;li&gt;output_add_rewrite_var — 添加URL重写器的值（Add URL rewriter values）&lt;/li&gt;
  &lt;li&gt;output_reset_rewrite_vars — 重设URL重写器的值（Reset URL rewriter values）&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;实例&quot;&gt;实例&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;for($i=0; $i&amp;lt;10; $i++) {
    echo &quot;$i sleeping .... &amp;lt;br&amp;gt;&quot;;
    echo &quot;&amp;lt;script type='text/javascript'&amp;gt; window.scrollTo(0, document.body.scrollHeight);&amp;lt;/script&amp;gt;&quot;
    ob_flush();
    flush();
    sleep(1);

}
echo &quot;&amp;lt;script type='text/javascript'&amp;gt; window.scrollTo(0, document.body.scrollHeight);&amp;lt;/script&amp;gt;&quot;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如上例子将会 每秒输出一个sleeping，挨个输出，而不是一次性输出, 此处ob_flush() 是把php的缓冲区内容送出到sapi缓冲区， flush()是把SAPI的缓冲区内容送出
两个函数共同实现了把echo的信息实时输出到浏览器，而不是一次性输出所有的echo信息。 js是用来控制浏览器滚动条一直在浏览器最底端， 也就是一直显示最新输出的内容.&lt;/p&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://gywbd.github.io/posts/2015/1/php-output-buffer-in-deep.html&quot;&gt;深入理解php输出缓存&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://php.net/manual/zh/ref.outcontrol.php&quot;&gt;输出控制函数&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://php.net/manual/zh/outcontrol.configuration.php&quot;&gt;输出控制运行时配置&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2016/06/07/php-output-buffering.html</link>
    <guid>http://huyongde.github.io/2016/06/07/php-output-buffering</guid>
    <pubDate>Tue, 07 Jun 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>xhprof 分析php应用程序的性能</title>
    <description>&lt;p&gt;主要是四个步骤&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;安装php xhprof扩展&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;代码入口加上xhprof的启用和分析数据收集的代码&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;分析数据可视化， xhprof_data目录需要修改权限，否则可能存在写分析数据和读分析数据失败的问题&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;安装graphviz 之前需要确定是否安装了libpng,最好自己安装一遍libpng, &lt;a href=&quot;https://www.cnxct.com/you-do-not-have-dot-image-generation-utility-installed/&quot;&gt;参考&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

</description>
    <link>http://huyongde.github.io/2016/05/26/php-xhprof.html</link>
    <guid>http://huyongde.github.io/2016/05/26/php-xhprof</guid>
    <pubDate>Thu, 26 May 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>apache配置</title>
    <description>&lt;h3 id=&quot;0-简介&quot;&gt;0. 简介&lt;/h3&gt;
&lt;p&gt;学习apache配置，主要是按照指令来学习，争取每天学习几个&lt;/p&gt;

&lt;h3 id=&quot;1-配置指令&quot;&gt;1. 配置指令&lt;/h3&gt;

&lt;h4 id=&quot;11-browsermatch&quot;&gt;1.1 BrowserMatch&lt;/h4&gt;
&lt;p&gt;对不同的UA进行一些特殊的配置，包括&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;nokeepalive 禁用keepalive; eg:BrowserMatch ^Mozilla nokeepalive&lt;/li&gt;
  &lt;li&gt;force-response-1.0 对所有请求强制进行http1.0的响应&lt;/li&gt;
  &lt;li&gt;downgrade-1.0 对所有的请求强制当作http 1.0 的请求来处理&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;例子:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;BrowserMatch “Mozilla/2” nokeepalive&lt;/li&gt;
  &lt;li&gt;BrowserMatch “MSIE 4.0b2;” nokeepalive downgrade-1.0 force-response-1.0&lt;/li&gt;
  &lt;li&gt;BrowserMatch “RealPlayer 4.0” force-response-1.0&lt;/li&gt;
  &lt;li&gt;BrowserMatch “Java/1.0” force-response-1.0&lt;/li&gt;
  &lt;li&gt;BrowserMatch “JDK/1.0” force-response-1.0&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;12-errordocument&quot;&gt;1.2 ErrorDocument&lt;/h4&gt;

&lt;p&gt;用来配置当出现特定的http code的时候提示文本或者转向的链接&lt;/p&gt;

&lt;p&gt;例子：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;ErrorDocument 400 “400 了, please check”&lt;/li&gt;
  &lt;li&gt;ErrorDocument 400 “/400.html”&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;13-rewrite&quot;&gt;1.3 rewrite&lt;/h4&gt;
&lt;p&gt;rewirte主要的功能就是实现URL的跳转，它的正则表达式是基于Perl语言。
可基于服务器级的(httpd.conf)和目录级的 (.htaccess)两种方式。
使用rewrite模块前，需要先安装或加载rewrite模块。&lt;/p&gt;

&lt;p&gt;基于服务器级的(httpd.conf)有两种方法，&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;一种是在httpd.conf的全局下直接利用RewriteEngine on来打开rewrite功能;&lt;/li&gt;
  &lt;li&gt;另一种是在局部里利用RewriteEngine on来打开rewrite功能&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;下面将会举例说明，需要注意的是,必须在每个virtualhost里用RewriteEngine on来打开rewrite功能。否则virtualhost里没有RewriteEngine on它里面的规则也不会生效。
基于目录级的(.htaccess),要注意一点那就是必须打开此目录的FollowSymLinks属性且在.htaccess里要声明RewriteEngine on。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;相关配置的指令&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;RewriteEngine 设置打开rewrite引擎, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RewriteEngine on&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;RewriteCond 为接下来的第一个RewriteRule，设置条件&lt;/li&gt;
  &lt;li&gt;RewriteRule  为满足前面RewriteCond设定的条件的URL，设置跳转规则&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;完整的例子:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;RewriteCond %{REQUEST_URI} ^/test/
RewriteCond %{REQUEST_URI} !^.*(.css|.js|.gif|.png|.jpg|.jpeg|.ico|.txt|.swf|.mp3|.mp4|.csv|.xls|.xlsx|.json)$
RewriteRule /test/(.*) /test/index.php
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;14-一些基本的设置&quot;&gt;1.4 一些基本的设置&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerRoot&lt;/code&gt;: 之处服务器保存其配置、错误日志和行为日志的根目录， &lt;strong&gt;路径的结尾不要加斜线&lt;/strong&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerRoot &quot;/usr/local/apache2&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PidFile&lt;/code&gt;: 设置服务进程，进程号的存放文件， 相对于ServerRoot的路径，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pidFile logs/httpd.pid&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeepAlive&lt;/code&gt;: 设置是否开启链接复用，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeepAlive On&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MaxKeepAliveRequests&lt;/code&gt;: 设置单个链接可以处理的最大请求数,&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MaxKeepAliveRequests 100&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Listen&lt;/code&gt;: 设置监听得的主机以及端口号&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExtendedStatus&lt;/code&gt;: 当调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server-status&lt;/code&gt;时，是否返回比较全面的信息&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExtendedStatus On&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LoadModule&lt;/code&gt;: 设置一些模块加载一些DSO模式编译的模块(DSO是Dynamic Shared Objects（动态共享目标）的缩写)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerName&lt;/code&gt;: 设定服务器的名字和端口号，和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Listen&lt;/code&gt; 区别开, 若是不能进行DNS解析的域名，可以直接用ip地址代替。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DocumentRoot&lt;/code&gt;: 设定文档的根目录，默认情况下，所有请求都从这个目录进行应答, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DocumentRoot &quot;/home/website/html&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Directory&amp;gt;&amp;lt;/Directory&amp;gt;&lt;/code&gt;: 设置Apache可以存取目录的存取权限&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DirectoryIndex&lt;/code&gt;: 定义请求是一个目录时，Apache向用户提供服务的文件名, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DirectoryIndex index.php index.htm index.html index.html.var&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnableSendfile&lt;/code&gt;: 设置是否支持sendfile, sendfile介绍见&lt;a href=&quot;http://huyongde.github.io/2015/12/20/nginx-sendfile-tcp_nodelay-tcp_nopush.html&quot;&gt;nginx sendfile配置&lt;/a&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnableSendfile On&lt;/code&gt; 设置 支持sendfile&lt;/li&gt;
  &lt;li&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ErrorLog&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LogLevel&lt;/code&gt;: 错误日志配置，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ErrorLog logs/error.log&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LogLevel warn&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomLog&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LogFormat&lt;/code&gt;: 指定access的记录文件，以及accessLog的格式&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LogFormat &quot;%h %l %u %t \&quot;%r\&quot; %&amp;gt;s %b \&quot;%{Referer}i\&quot; \&quot;%{User-Agent}i\&quot; %I %O&quot; combinedio&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomLog logs/access_log combinedio&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerTokens&lt;/code&gt; 设置http response header中server的信息，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Server:Apache&lt;/code&gt;. 默认为“Full”， 这表示在回应头中将包含模块中的操作系统类型和编译信息。可以设为列各值中的一个： Full&lt;/td&gt;
          &lt;td&gt;OS&lt;/td&gt;
          &lt;td&gt;Minor&lt;/td&gt;
          &lt;td&gt;Minimal&lt;/td&gt;
          &lt;td&gt;Major&lt;/td&gt;
          &lt;td&gt;Prod. Full传达的信息最多，而Prod最少。&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;15-virtualhost-update-on-2016-05-22-222710-&quot;&gt;1.5 VirtualHost (update on 2016-05-22 22:27:10 )&lt;/h4&gt;

&lt;p&gt;VirtualHost 通过设置虚拟主机，来实现一个机器多个域名，多个主机名等
看几个例子:&lt;/p&gt;

&lt;h4 id=&quot;151-一个ip上部署多个服务&quot;&gt;1.5.1 一个IP上部署多个服务&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Listen 80
NameVirtualHost *:80
&amp;lt;VirtualHost *:80&amp;gt;
    DocumentRoot /www/example1
    ServerName www.example1.com
    # 其他的一些指令配置
&amp;lt;/VirtualHost&amp;gt;

&amp;lt;VirtualHost *:80&amp;gt;
    DocumentRoot /www/example2
    ServerName www.example2.com
    # 其他的指令配置

&amp;lt;/VirtualHOst&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;多个虚拟主机域名时，当一个不存在的主机域名请求到来时，第一个虚拟主机会服务这个请求&lt;/strong&gt;&lt;/p&gt;

&lt;h4 id=&quot;152-不同的域名部署在不同的ip上&quot;&gt;1.5.2 不同的域名部署在不同的IP上&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;##主服务 运行在172.20.30.40 上
ServerName server.domain.com
DocumentRoot /www/mainserver

###另一个IP
NameVirtualHost 172.20.30.50

&amp;lt;VirtualHost 172.20.30.50&amp;gt;
    DocumentRoot /www/example1
    ServerName www.example1.com
    # 其他的一些指令配置
&amp;lt;/VirtualHost&amp;gt;

&amp;lt;VirtualHost 172.20.30.50&amp;gt;
    DocumentRoot /www/example2
    ServerName www.example2.com
    # 其他的一些指令配置
&amp;lt;/VirtualHost&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;所有不是到.50IP 的请求都是主服务来服务， 所有到.50的，不带Host,或者host不是www.example1.com 和 www.example2.com的都将被第一个虚拟主机来服务&lt;/strong&gt;&lt;/p&gt;

&lt;h4 id=&quot;153-多个ip上部署同一个服务&quot;&gt;1.5.3 多个IP上部署同一个服务&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NameVirtualHost 192.168.0.1
NameVirtualHost 172.20.30.40

&amp;lt;VirtualHost 192.168.0.1 172.20.30.40&amp;gt;
    DocumentRoot /www/server
    ServerName www.server.example.com
    ServerAlias server
&amp;lt;/VirtualHost&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;可以通过serverAlias server来代替www.server.example.com域名来访问服务&lt;/strong&gt;&lt;/p&gt;

&lt;h4 id=&quot;154-不同的端口部署不同的服务&quot;&gt;1.5.4 不同的端口部署不同的服务&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Listen 80
Listen 8080

NameVirtualHost 172.20.30.40:80
NameVirtualHost 172.20.30.40:8080

&amp;lt;VirtualHost 172.20.30.40:80&amp;gt;
    ServerName www.example1.com
    DocumentRoot /www/domain-80
&amp;lt;/VirtualHost&amp;gt;

&amp;lt;VirtualHost 172.20.30.40:8080&amp;gt;
    ServerName www.example1.com
    DocumentRoot /www/domain-8080
&amp;lt;/VirtualHost&amp;gt;

&amp;lt;VirtualHost 172.20.30.40:80&amp;gt;
    ServerName www.example2.org
    DocumentRoot /www/otherdomain-80
&amp;lt;/VirtualHost&amp;gt;

&amp;lt;VirtualHost 172.20.30.40:8080&amp;gt;
    ServerName www.example2.org
    DocumentRoot /www/otherdomain-8080
&amp;lt;/VirtualHost&amp;gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;16-目录访问权限控制&quot;&gt;1.6 目录访问权限控制&lt;/h4&gt;
&lt;p&gt;主要指令: Order, Allow, Deny。 Order来控制指令Allow和Deny的生效顺序,&lt;/p&gt;

&lt;p&gt;也就是说Allow和deny的生效顺序和他们在配置中的位置没有关系，和Order的配置有关。&lt;/p&gt;

&lt;p&gt;下面看几个例子&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;Directory /www/web&amp;gt;
    Order Allow Deny
    Allow from all
    Deny from 112.10.20.30
    ### 先允许所有用户访问再拒绝ip112.10.20.30的访问

&amp;lt;/Directory&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;Directory /web&amp;gt;
    Order Deny,Allow
    Deny from 112.2.10.2
    Allow from all
    Deny from 123.10.10.1
    #先拒绝112.2.10.2访问
    #再拒绝123.10.10.1访问
    #最后允许所有用户访问
    #总结：允许所有用户访问
    #(即使Allow指令在Deny指令前，但是根据Order Deny,Allow语句，仍然先看Deny，再看Allow)
&amp;lt;/Directory&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;17-rotatelogs进行日志的切分&quot;&gt;1.7 rotatelogs进行日志的切分&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotatelogs&lt;/code&gt; 可以按照日期或者日志文件大小对日志进行切分.
前面介绍了CustomLog和ErrorLog指令都可以用配合&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotatelogs&lt;/code&gt;使用，&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CustomLog logs/access.log combinedio

ErrorLog logs/error.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;可以修改为 按照时间来切分日志&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CustomLog &quot;| /usr/sbin/rotatelogs -l logs/access-%Y%m%d.log 86400&quot; combinedio

ErrorLog &quot;| /usr/sbin/rotatelogs -l logs/error-%Y%m%d.log 86400&quot; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这样后，会把access.log 和 error.log按照时间进行切分，到达指定的时间点后会对日志进行切分，
86400指定了多长时间进行一次日志切分，单位是秒，如上设置是1天进行一次日志切分， 会产生类似如下文件名的日志文件：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;access-20160616.log

error-20160616.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;还可以修改为 按照时间来切分日志&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CustomLog &quot;| /usr/sbin/rotatelogs  logs/access-%Y%m%d.log 100M&quot; combinedio

ErrorLog &quot;| /usr/sbin/rotatelogs logs/error-%Y%m%d.log 50M&quot; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;修改之后，access.log达到100M之后会进行日志切分，error.log日志达到50M后会进行切分，都会加上当前日期的后缀，&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;总结rotatelogs用法&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;格式: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotatelogs [ -l ] logfile [ rotationtime [ offset ]] | [ filesizeM ]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;参数说明&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;-l 使用本地时间代替GMT时间作为时间基准。&lt;/li&gt;
      &lt;li&gt;logfile 日志文件名&lt;/li&gt;
      &lt;li&gt;rotationtime 日志切分进行的时间间隔， 时间单位秒&lt;/li&gt;
      &lt;li&gt;offet 相对UTC的时差分钟数， 可以省略，如果省略， 则假定为0并使用UTC时间&lt;/li&gt;
      &lt;li&gt;filesizeM 指定文件达到多大时进行切分，文件大小单位是M&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;配置切分日志格式的字符串&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;星期名全称(本地的)&lt;/li&gt;
  &lt;li&gt;%a 3个字符的星期名(本地的)&lt;/li&gt;
  &lt;li&gt;%B 月份名的全称(本地的)&lt;/li&gt;
  &lt;li&gt;%b 3个字符的月份名(本地的)&lt;/li&gt;
  &lt;li&gt;%c 日期和时间(本地的)&lt;/li&gt;
  &lt;li&gt;%d 2位数的一个月中的日期数&lt;/li&gt;
  &lt;li&gt;%H 2位数的小时数(24小时制)&lt;/li&gt;
  &lt;li&gt;%I 2位数的小时数(12小时制)&lt;/li&gt;
  &lt;li&gt;%j 3位数的一年中的日期数&lt;/li&gt;
  &lt;li&gt;%M 2位数的分钟数&lt;/li&gt;
  &lt;li&gt;%m 2位数的月份数&lt;/li&gt;
  &lt;li&gt;%p am/pm12小时制的上下午(本地的)&lt;/li&gt;
  &lt;li&gt;%S 2位数的秒数&lt;/li&gt;
  &lt;li&gt;%U 2位数的一年中的星期数(星期天为一周的第一天)&lt;/li&gt;
  &lt;li&gt;%W 2位数的一年中的星期数(星期一为一周的第一天)&lt;/li&gt;
  &lt;li&gt;%w 1位数的星期几(星期天为一周的第一天)&lt;/li&gt;
  &lt;li&gt;%X 时间(本地的)&lt;/li&gt;
  &lt;li&gt;%x 日期(本地的)&lt;/li&gt;
  &lt;li&gt;%Y 4位数的年份&lt;/li&gt;
  &lt;li&gt;%y 2位数的年份&lt;/li&gt;
  &lt;li&gt;%Z 时区名&lt;/li&gt;
  &lt;li&gt;%% 符号”%”本身&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;未完待续&lt;/p&gt;

&lt;h4 id=&quot;参考&quot;&gt;参考&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://wiki.ubuntu.org.cn/index.php?title=Apache%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6httpd.conf%E5%86%85%E5%AE%B9%E7%BF%BB%E8%AF%91&amp;amp;variant=zh-hans&quot;&gt;apache配置文件httpd.conf内容翻译&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2016/05/03/apache-httpd-conf.html</link>
    <guid>http://huyongde.github.io/2016/05/03/apache-httpd-conf</guid>
    <pubDate>Tue, 03 May 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>正则表达式学习整理(一)</title>
    <description>&lt;h3 id=&quot;0-简介&quot;&gt;0. 简介&lt;/h3&gt;

&lt;p&gt;下雨天在家，看看资料，再熟悉下正则表达式， 参考的文档是 &lt;a href=&quot;http://deerchao.net/tutorials/regex/regex.htm&quot;&gt;正则表达式入门&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;本次主要是记录正则表达式相关的元字符、字符转义、重复、字符类、分枝条件、分组、反义、反向引用、零宽断言、负向零宽断言、贪婪与懒惰、处理选项等&lt;/p&gt;

&lt;h3 id=&quot;1-元字符&quot;&gt;1. 元字符&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;元字符分几部分，主要包括用来表示字符的，用来表示位置的，用来表示重复次数的.&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;字符&lt;/th&gt;
      &lt;th&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;匹配除换行以外的任意字符&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\w&lt;/td&gt;
      &lt;td&gt;匹配字符数字下划线汉字&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\s&lt;/td&gt;
      &lt;td&gt;匹配空白字符&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\d&lt;/td&gt;
      &lt;td&gt;匹配数字&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\b&lt;/td&gt;
      &lt;td&gt;匹配单词的开始和结束&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;^&lt;/td&gt;
      &lt;td&gt;匹配行内字符串的开始&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$&lt;/td&gt;
      &lt;td&gt;匹配行内字符串的结束&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;2-字符转义&quot;&gt;2. 字符转义&lt;/h3&gt;

&lt;p&gt;对于元字符本身，如果想单纯的匹配元字符本身，需要用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&lt;/code&gt; 对元字符进行转义， 比如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\.&lt;/code&gt; 匹配小数点， &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\*&lt;/code&gt; 匹配星号(*)&lt;/p&gt;

&lt;h3 id=&quot;3-重复&quot;&gt;3. 重复&lt;/h3&gt;
&lt;p&gt;代码和语法|说明
——–|——&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;重复零次或者更多次&lt;/td&gt;
          &lt;td&gt; &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;?&lt;/td&gt;
          &lt;td&gt;重复零次或者一次&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;重复一次或者更多次&lt;/td&gt;
          &lt;td&gt; &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;{n}&lt;/td&gt;
          &lt;td&gt;重复n次&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;{m,}&lt;/td&gt;
          &lt;td&gt;重复m,或者大于m次&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;{m,n}&lt;/td&gt;
          &lt;td&gt;重复m到n次之间&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;几个例子：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;\d+ 匹配1个或者多个数字，等价于 \d{1,}&lt;/li&gt;
  &lt;li&gt;[a-b]{1,3} 匹配1到3个小写字母&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;4-字符类&quot;&gt;4. 字符类&lt;/h3&gt;

&lt;p&gt;要查找元字符可以表示的字符类是很简单的，比如\d 表示数字字符集。 对于查找没有预定义的字符集，需要用方括号括起来，表示需要匹配的字符集。&lt;/p&gt;

&lt;p&gt;如: [aeiou] 表示匹配所有的元字母； [0-5] 表示匹配0到5中任一数字; [,!\?]  匹配标点符号(,!?)&lt;/p&gt;

&lt;h3 id=&quot;5-分支条件&quot;&gt;5. 分支条件&lt;/h3&gt;
&lt;p&gt;linux 命令grep 如果想要查找多个字符串， 可以用-e 选项来指定，也可以用正则表达式的分支条件来实现 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep -e hello -e world&lt;/code&gt; 等级于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep -E &quot;hello|world&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;正则表达式的分支条件是通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt; 来实现的, 就是用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt; 把不同的多个匹配规则分割开， 只要满足一个规则就是匹配成功。&lt;/p&gt;

&lt;h3 id=&quot;6-分组&quot;&gt;6. 分组&lt;/h3&gt;

&lt;p&gt;在前面&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\d+&lt;/code&gt; 可以实现对单个字符的重复次数的匹配， 如何实现匹配多个字符的重复次数呢？ 可以通过小括号&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; 来指定子表达式规则(也成为分组), 然后就可以指定这个子表达式的重复次数了。&lt;/p&gt;

&lt;p&gt;几个例子:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;(\d{1,3}\.){3}\d{1,3} 可以简单的匹配一个ip地址， 如 113.44.60.124, 只是能简单的匹配，没能做到判断ip是否合法&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;7-反义元字符&quot;&gt;7. 反义元字符&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;代码语法&lt;/th&gt;
      &lt;th&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;\W&lt;/td&gt;
      &lt;td&gt;匹配任意不是字母数字下划线汉字的字符&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\S&lt;/td&gt;
      &lt;td&gt;匹配任意不是空白字符的字符&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\D&lt;/td&gt;
      &lt;td&gt;匹配任意不是数字的字符&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\B&lt;/td&gt;
      &lt;td&gt;匹配任意不是单词开始或者结束的位置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;[\^x]&lt;/td&gt;
      &lt;td&gt;匹配任意不是x的字符&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;[\^aeiou]&lt;/td&gt;
      &lt;td&gt;匹配任意不是 a e i o u 这几个字符的字符&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;如： \S+ 匹配不包含空格的字符串; &amp;lt;a[^&amp;gt;]+&amp;gt;  匹配用&amp;lt;&amp;gt; 括起来并且以a开头的字符串&lt;/p&gt;

&lt;h3 id=&quot;8-反向引用&quot;&gt;8. 反向引用&lt;/h3&gt;
&lt;p&gt;通过小括号匹配一个子表达式分组后，可以在匹配之后用来做一些处理， 每一个匹配到的子表达式分组都对应一个可以用来反向引用的分组号， 
分组号的规则是: 从左向右依照左边括号出现的次序来分配分组号，第一次出现的左小括号对应的分组的分组号是1， 以此类推2，3，….。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;反向引用：可以用来匹配之前某个分组匹配的字符， 例如， 通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\1&lt;/code&gt; 代表分组1 匹配的字符。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;例子： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\b(\w+)\b\s+\1\b&lt;/code&gt; 匹配连续出现的单词， 如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go go&lt;/code&gt; , &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello hello&lt;/code&gt; 等&lt;/p&gt;

&lt;p&gt;对于子表达式分组的分组号除了默认的数字编号表示外，还可以为每个子表达式自定义分组名. 
**指定子表达式分组名的方式为: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(?&amp;lt;word&amp;gt;\w+)&lt;/code&gt; ** , 还可以把尖括号换成&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;'&lt;/code&gt;  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(?'word'\w+)&lt;/code&gt;  这样就把分组名设定为了word
反向引用这个分组匹配的字符串通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\k&amp;lt;word&amp;gt;&lt;/code&gt;  。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;使用语法 \k&lt;名称&gt; 在同一正则表达式中引用匹配的子表达式，其中名称是捕获子表达式的名称。&lt;/名称&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;常用的分组语法如下表:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;分类&lt;/th&gt;
      &lt;th&gt;代码语法&lt;/th&gt;
      &lt;th&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;捕获&lt;/td&gt;
      &lt;td&gt;(exp)&lt;/td&gt;
      &lt;td&gt;匹配exp, 并捕获文本到自动命名的组里面&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;捕获&lt;/td&gt;
      &lt;td&gt;(?&amp;lt;name&amp;gt;exp)&lt;/td&gt;
      &lt;td&gt;匹配exp, 并捕获文本到名称为name的组里面&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;捕获&lt;/td&gt;
      &lt;td&gt;(?:exp)&lt;/td&gt;
      &lt;td&gt;匹配exp,不捕获文本，也不为文本自动分配组名称&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;零点断言&lt;/td&gt;
      &lt;td&gt;(?=exp)&lt;/td&gt;
      &lt;td&gt;匹配exp前面的位置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;零点断言&lt;/td&gt;
      &lt;td&gt;(?&amp;lt;=exp)&lt;/td&gt;
      &lt;td&gt;匹配exp后面的位置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;零点断言&lt;/td&gt;
      &lt;td&gt;(?!exp)&lt;/td&gt;
      &lt;td&gt;匹配后面跟的不是exp的位置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;零点断言&lt;/td&gt;
      &lt;td&gt;(?&amp;lt;!exp)&lt;/td&gt;
      &lt;td&gt;匹配前面不是exp的位置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;注释&lt;/td&gt;
      &lt;td&gt;(?#comment)&lt;/td&gt;
      &lt;td&gt;这种类型的分组不对正则表达式的处理产生任何影响，用于提供注释让人阅读&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;(exp) 和 (?&amp;lt;name&amp;gt;exp) 这两种分组的语法我们已经学习到了， 第三个(?:exp) 只匹配不捕获的，接下来介绍下使用场景&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;9-零宽断言&quot;&gt;9. 零宽断言&lt;/h3&gt;
&lt;p&gt;零宽断言用来查找某些内容之前或者之后的字符， 就像\b, ^ 和 $ 三个元字符一样，用来指定一个位置，这个位置应该满足一定的条件，
因为只是匹配一个位置，所以叫零宽断言&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;(?=exp) 匹配exp之前的位置, 被匹配到的字符串的后面紧跟表达式exp. 比如:&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\b\w(?=ing\b)&lt;/code&gt; 匹配以ing结尾的单词的ing前面的部分,
 如果在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;I am singing while you are dancing&lt;/code&gt; 进行匹配会匹配到sing 和 danc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;(?&amp;lt;=exp) 匹配exp之后的位置，被匹配到的字符的前面是exp表达式代表的字符， 比如: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(?&amp;lt;=\bre)\w\b&lt;/code&gt;, 匹配re开头的单词re后面部分的字符串，匹配
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reading a book&lt;/code&gt; 时，会匹配到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ading&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;10-负向零宽断言&quot;&gt;10. 负向零宽断言&lt;/h3&gt;

</description>
    <link>http://huyongde.github.io/2016/05/02/regex-learn.html</link>
    <guid>http://huyongde.github.io/2016/05/02/regex-learn</guid>
    <pubDate>Mon, 02 May 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>http 传递数组形式的参数</title>
    <description>&lt;h3 id=&quot;http两中传参方式&quot;&gt;http两中传参方式&lt;/h3&gt;
&lt;h4 id=&quot;1普通字符串&quot;&gt;1.普通字符串&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;eg:  a=1&amp;amp;b=2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;2数组&quot;&gt;2.数组&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;info[name]=huyongde&amp;amp;info[age]=20
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;后端&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$_GET['info']&lt;/code&gt;或者&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$_POST['info']&lt;/code&gt; 是一个数组，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;array('name'=&amp;gt;'huyongde', 'age'=&amp;gt;20);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;** 注意：无论post还是Get请求都是可以传递数组参数奥。**&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2016/04/29/http-array-params.html</link>
    <guid>http://huyongde.github.io/2016/04/29/http-array-params</guid>
    <pubDate>Fri, 29 Apr 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>vim 配置(二) -- map 类操作</title>
    <description>&lt;h3 id=&quot;0-简介&quot;&gt;0. 简介&lt;/h3&gt;
&lt;p&gt;通过map可以配置vim一些快捷键操作，比如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map &amp;lt;C-a&amp;gt; ggVG&lt;/code&gt; 来设置&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+a&lt;/code&gt; 选择vim正在编辑的文件的所用内容。
在介绍map命令之前，先介绍一下vim的不同模式，在vim不同模式下都有对应的map操作。&lt;/p&gt;

&lt;h3 id=&quot;1-vim-模式&quot;&gt;1. VIM 模式&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Normal Mode: 普通模式，vim打开文件默认就是这种模式，从其他模式通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;esc&lt;/code&gt; 切换到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;normal mode&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Visual Mode: 可视模式， vim在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;normal mode&lt;/code&gt;下通过按键&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v&lt;/code&gt; 进入可视模式,可视模式下可以选定多个字符，多行,多列等。&lt;/li&gt;
  &lt;li&gt;Insert Mode: 插入模式，在插入模式下，可以进行文本的编辑，从&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Normal Mode&lt;/code&gt; 通过按键&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; 进入插入模式, 通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;esc&lt;/code&gt;键返回&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Normal Mode&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;Select Mode: 选择模式， 在选择模式下可以选择多行或者多个字符，此模式下选择某些文本之后，进行的任何键的输入都是直接替换选择的文本，
和windows下面用鼠标选择一部分文本进行替换是一个原理。 从&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Normal Mode&lt;/code&gt; 通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gh&lt;/code&gt;切换到选择模式。&lt;/li&gt;
  &lt;li&gt;Command-Line/EX-Mode: 命令行模式和EX 模式, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Normal Mode&lt;/code&gt; 下按&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt; 进入命令行模式，可以进行一些命令操作，比如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w, q, x, set paste&lt;/code&gt;等.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Normal Mode&lt;/code&gt; 下按&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Q&lt;/code&gt; 进入EX模式，是多行的命令行模式。&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;如上介绍了vim的几种模式， 下面看下每种模式和map的关系&lt;/p&gt;

&lt;/blockquote&gt;

&lt;h3 id=&quot;2-vim-各模式下的map&quot;&gt;2. vim 各模式下的map&lt;/h3&gt;

&lt;p&gt;vim 通过map不同的前缀来表示此快捷键设置生效的模式。如nmap 表示nmap设置的快捷键是在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Normal Mode&lt;/code&gt;下生效。&lt;/p&gt;

&lt;p&gt;不同模式对应的map前缀不一样, 下面给出不同map前缀对应的vim模式&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;map前缀&lt;/th&gt;
      &lt;th&gt;生效模式&lt;/th&gt;
      &lt;th&gt;相关map命令&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;n&lt;/td&gt;
      &lt;td&gt;普通模式&lt;/td&gt;
      &lt;td&gt;nmap, nnoremap, nunmap, nmapclear&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;v&lt;/td&gt;
      &lt;td&gt;可视模式 和 选择模式&lt;/td&gt;
      &lt;td&gt;vmap, vnoremap, vunmap, vmapclear&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;x&lt;/td&gt;
      &lt;td&gt;可视模式&lt;/td&gt;
      &lt;td&gt;xmap,xnoremap, xunmap, xmapclear&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;s&lt;/td&gt;
      &lt;td&gt;选择模式&lt;/td&gt;
      &lt;td&gt;smap, snoremap, sunmap, smapclear&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;i&lt;/td&gt;
      &lt;td&gt;插入模式&lt;/td&gt;
      &lt;td&gt;imap, inoremap, iunmap, imapclear&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;c&lt;/td&gt;
      &lt;td&gt;命令行模式&lt;/td&gt;
      &lt;td&gt;cmap, cnoremap, cunmap, cmapclear&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;无前缀&lt;/td&gt;
      &lt;td&gt;普通模式和可视模式&lt;/td&gt;
      &lt;td&gt;map, noremap, unmap, mapclear&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;blockquote&gt;
  &lt;p&gt;其中unmap是取消某些快捷键绑定， *clear是清除某些模式下的所有快捷键映射, nore是非递归映射.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;3-非递归映射&quot;&gt;3. 非递归映射&lt;/h3&gt;

&lt;p&gt;递归映射, 其实很好理解，也就是如果键a被映射成了b，c又被映射成了a，如果映射是递归的，那么c就被映射成了b.
默认map是递归的映射，通过前缀&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nore&lt;/code&gt; (no recursion)来实现非递归的映射, 如 nnoremap.&lt;/p&gt;

&lt;h3 id=&quot;4-特殊键列表&quot;&gt;4. 特殊键列表&lt;/h3&gt;
&lt;p&gt;特殊按键|说明
—–|——
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;k0&amp;gt; - &amp;lt;k9&amp;gt;&lt;/code&gt;| 小键盘 0 到 9 &lt;em&gt;keypad-0&lt;/em&gt; &lt;em&gt;keypad-9&lt;/em&gt; 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;S-...&amp;gt;&lt;/code&gt; | Shift＋键 &lt;em&gt;shift&lt;/em&gt; &lt;em&gt;&amp;lt;S-&lt;/em&gt; 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;C-...&amp;gt;&lt;/code&gt; | Control＋键 &lt;em&gt;control&lt;/em&gt; &lt;em&gt;ctrl&lt;/em&gt; &lt;em&gt;&amp;lt;C-&lt;/em&gt; 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;M-...&amp;gt;&lt;/code&gt; | Alt＋键 或 meta＋键 &lt;em&gt;meta&lt;/em&gt; &lt;em&gt;alt&lt;/em&gt; &lt;em&gt;&amp;lt;M-&lt;/em&gt; 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;A-...&amp;gt;&lt;/code&gt; |  同 &lt;m-...&gt; *&amp;lt;A-* 
`&lt;D-...&gt;` | Command＋键 *control* *ctrl* *&amp;lt;C-*&lt;/D-...&gt;&lt;/m-...&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Esc&amp;gt;&lt;/code&gt;代表Escape键;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;CR&amp;gt;&lt;/code&gt;代表Enter键；&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;D&amp;gt;&lt;/code&gt;代表Cond键。
Alt键可以使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;M-key&amp;gt;&lt;/code&gt;或&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;A-key&amp;gt;&lt;/code&gt;来表示。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;C&amp;gt;&lt;/code&gt;代表Ctrl.
对于组合键，可以用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;C-Esc&amp;gt;&lt;/code&gt;代表Ctrl-Esc；使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;S-F1&amp;gt;&lt;/code&gt;表示Shift-F1.&lt;/p&gt;

&lt;h3 id=&quot;5-map特殊参数&quot;&gt;5. map特殊参数&lt;/h3&gt;

&lt;p&gt;特殊参数必须紧跟在映射命令(map, nmap等)的后边，在其他任何参数的前面。 
有如下特殊参数&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;buffer&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;silent&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;special&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;script&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;expr&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;unique&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;后续继续研究特殊参数&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;6-举个栗子&quot;&gt;6. 举个栗子&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &quot;&quot; Ctrl + a全选文本
map &amp;lt;C-a&amp;gt; ggVG 

 &quot;&quot; Normal Mode F7 打开或者关闭NERDTree插件
nnoremap &amp;lt;silent&amp;gt; &amp;lt;F7&amp;gt; :NERDTreeToggle&amp;lt;cr&amp;gt;

&quot;&quot; Normal Mode F8 打开或者关闭TList插件
nnoremap &amp;lt;silent&amp;gt; &amp;lt;F8&amp;gt; :TlistToggle&amp;lt;CR&amp;gt;

 &quot;&quot; Normal Mode gl 是跳转到上次修改的位置
nnoremap gl `. 

 &quot;&quot; 插入模式下mm进入Normal Mode
inoremap mm    &amp;lt;ESC&amp;gt;

 &quot;&quot;Normal Mode下，&quot;,dt&quot; 在当前光标后面添加日期时间
nmap ,dt a&amp;lt;C-R&amp;gt;=strftime('%Y-%m-%d %H:%M:%S')&amp;lt;CR&amp;gt; 

 &quot;&quot;Insert Mode下，&quot;,dt&quot; 在当前光标后面添加日期时间
imap ,dt &amp;lt;C-R&amp;gt;=strftime('%Y-%m-%d %H:%M:%S')&amp;lt;CR&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;参考&quot;&gt;参考&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.douban.com/group/topic/10866937/&quot;&gt;vim map&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://haoxiang.org/2011/09/vim-modes-and-mappin/&quot;&gt;vim的几种模式和按键映射&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;help map&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2016/04/04/vim-map.html</link>
    <guid>http://huyongde.github.io/2016/04/04/vim-map</guid>
    <pubDate>Mon, 04 Apr 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>VIM 配置(一)--基础篇</title>
    <description>&lt;h3 id=&quot;0-简介&quot;&gt;0. 简介&lt;/h3&gt;

&lt;p&gt;vim配置弄过很多，关于编码的，缩进的，taglist, nerdtree， vundle插件管理器等的配置。假期有空重新整理学习学习&lt;/p&gt;

&lt;p&gt;准备从如下几个方面去整理：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;vim基础配置学习，如编码，缩进&lt;/li&gt;
  &lt;li&gt;vim各项配置命令学习,如map, aotocmd, command等等&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://huyongde.github.io/2016/01/02/vim-plugin-bundler-vundle.html&quot;&gt;vundle 安装使用&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;自动代码格式化&lt;/li&gt;
  &lt;li&gt;各语言代码语法自动检查&lt;/li&gt;
  &lt;li&gt;代码补全&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;本篇主要介绍下vim相关的基础配置&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;1-相关配置&quot;&gt;1. 相关配置&lt;/h3&gt;
&lt;p&gt;####1.1 设置保存vimrc自动生效&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autocmd! bufwritepost .vimrc source ~/.vimrc&lt;/code&gt; 设置之后，&lt;/li&gt;
  &lt;li&gt;当你修改~./vimrc并执行:w保存时可能会报 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E174: Command already exists: add ! to replace it&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;superuser有关于这个问题的解决方案，&lt;a href=&quot;http://superuser.com/questions/830132/sourcing-the-vimrc-gives-e174-error&quot;&gt;解决source ~/.vimrc E174&lt;/a&gt;
主要就是你需要在command后面加上!来做vim的相关配置。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;:help E174&lt;/strong&gt;的结果是&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:com[mand][!] [{attr}...] {cmd} {rep}
定义一个用户命令。命令的名字是 {cmd}，而替换的文本是
{rep}。该命令的属性 (参考下面) 是 {attr}。如果该命令已
存在，报错，除非已经指定了一个 !，这种情况下命令被重定
义。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;设置完成上面两步之后，就可以在修改了~/.vimrc并保存的时候，自动执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source ~/.vimrc&lt;/code&gt; 来使配置生效了。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;12-vim配置help的中文文档&quot;&gt;1.2 vim配置help的中文文档&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;首先下载vimdoc,&lt;a href=&quot;http://jaist.dl.sourceforge.net/project/vimcdoc/vimcdoc/vimcdoc-1.9.0.tar.gz&quot;&gt;下载链接&lt;/a&gt; ,vimdoc官网&lt;a href=&quot;http://vimcdoc.sourceforge.net/&quot;&gt;主页&lt;/a&gt;, 
下载后直接把压缩包放入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.vim/doc&lt;/code&gt; 目录，不存在的话进行创建&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkdir -p ~/.vim/doc&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:helptags ~/.vim/doc&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.vimrc &lt;/code&gt; 中设置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set helplang=cn&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;上面三步一步不少的执行完后，就可以愉快的看到中文版的vim help了， 可以help autocmd验证下&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;13-编码配置&quot;&gt;1.3 编码配置&lt;/h4&gt;

&lt;p&gt;vim 中有四个关于编码的选项，分别是encoding(enc), termencoding(tenc), fileencoding(fenc), fileencodings(fencs). 下面分别介绍这四种编码：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;encoding(enc) : encoding 是vim内部使用的字符编码方式，vim内部所有的buffer,寄存器， 脚本中的字符串都是使用此编码。 
vim工作时，遇到编码和内部编码不一致时， 会把编码转化为内部编码，无法转化的部分就会丢失。&lt;/li&gt;
  &lt;li&gt;termencoding(tenc) : termencoding 是vim用于屏幕显示的编码, 在显示的时候vim会把内部编码转化为屏幕编码，再用于输出。
无法从内部编码转化为屏幕编码的字符，显示的时候将会变成问号。 若termencoding不设置，则屏幕编码直接使用encoding的设置。&lt;/li&gt;
  &lt;li&gt;fileencoding(fenc) : 当vim从磁盘上读取文件的时候，会对文件的编码进行探测。如果文件的编码方式和 vim 的内部编码方式不同，vim 就会对编码进行转换。
转换完毕后，Vim 会将 fileencoding 选项设置为文件的编码。当 Vim 存盘的时候，如果 encoding 和 fileencoding 不一样，Vim 就会进行编码转换。
因此，通过打开文件后设置 fileencoding，我们可以将文件由一种编码转换为另一种编码。但是，由前面的介绍可以看出，fileencoding 是在打开文件的时候 ，
由 Vim 进行探测后自动设置的。因此，如果出现乱码，我们无法通过在打开文件后重新设置 fileencoding 来纠正乱码。&lt;/li&gt;
  &lt;li&gt;fileencodings(fencs) :  编码的自动识别是通过设置 fileencodings 实现的，注意是复数形式。
fileencodings 是一个用逗号分隔的列表，列表中的每一项是一种编码的名称。当我们打开文件的时候，
VIM 按顺序使用 fileencodings 中的编码进行尝试解码，如果成功的话，就使用该编码方式进行解码，
并将 fileencoding 设置为这个值，如果失败的话，就继续试验下一个编码。 因此，我们在设置 fileencodings 的时候，
一定要把要求严格的、当文件不是这个编码的时候更容易出现解码失败的编码方式放在前面，把宽松的编码方式放在后面。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;参考学习&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.vimer.cn/2009/10/87.html&quot;&gt;vim解决中文乱码问题&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://edyfox.codecarver.org/html/vim_fileencodings_detection.html&quot;&gt;vim文件编码识别设置&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/mbbill/fencview&quot;&gt;mbbill/fencview&lt;/a&gt; 文件编码自动检测插件&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;14-缩进配置&quot;&gt;1.4 缩进配置&lt;/h4&gt;

&lt;p&gt;参考学习&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://linux-wiki.cn/wiki/zh-hans/Vim%E4%BB%A3%E7%A0%81%E7%BC%A9%E8%BF%9B%E8%AE%BE%E7%BD%AE&quot;&gt;vim缩进配置&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;补充&quot;&gt;补充&lt;/h3&gt;
&lt;h4 id=&quot;设置php文件保存的时候自动进行php--l的php语法检查&quot;&gt;设置php文件保存的时候自动进行php -l的php语法检查&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;第一种方法，不借助插件的配置&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autocmd! BufWritePost *.php :!php -l %&lt;/code&gt; 
是通过php -l来执行，做了一次自动命令的来实现的,当写php文件的时候，自动执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:!php -l %&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/scrooloose/syntastic&quot;&gt;vim 各语言的语法检查插件&lt;/a&gt;  &lt;a href=&quot;https://github.com/scrooloose/syntastic/wiki/Syntax-Checkers&quot;&gt;相关wiki&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;phplint 进行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt; Bundle 'nrocco/vim-phplint'&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autocmd! BufWritePost *.php :phplint&lt;/code&gt; 两个配置，第一个配置是安装phplint插件，第二个配置是在文件写入时自动执行phplint插件
&lt;a href=&quot;https://github.com/nrocco/vim-phplint&quot;&gt;Phplint github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;最终我选择的Phplint，显示的结果更友好些。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;php文件保存的时候自动进行代码格式化&quot;&gt;php文件保存的时候自动进行代码格式化&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;不借助插件来实现 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autocmd! BufWrite *.php :exec 'normal ggVG==='&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;vim各类代码格式化的插件&lt;a href=&quot;https://github.com/Chiel92/vim-autoformat&quot;&gt;Chiel92/vim-autoformat&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;楼主目前用的非插件的antocmd配置方式， 后续研究下插件方式的&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5 id=&quot;接下来准备研究下vim的map类命令vim的几种模式和按键映射&quot;&gt;接下来准备研究下vim的map类命令&lt;a href=&quot;http://haoxiang.org/2011/09/vim-modes-and-mappin/&quot;&gt;vim的几种模式和按键映射&lt;/a&gt;&lt;/h5&gt;
&lt;h5 id=&quot;学习下vim插件推荐-文章中推荐的插件&quot;&gt;学习下&lt;a href=&quot;http://edyfox.codecarver.org/html/vimplugins.html&quot;&gt;vim插件推荐&lt;/a&gt; 文章中推荐的插件&lt;/h5&gt;
&lt;h5 id=&quot;楼主现在用的vim配置&quot;&gt;楼主现在用的&lt;a href=&quot;https://github.com/huyongde/my.vimrc&quot;&gt;vim配置&lt;/a&gt;&lt;/h5&gt;
</description>
    <link>http://huyongde.github.io/2016/04/02/vim-configure.html</link>
    <guid>http://huyongde.github.io/2016/04/02/vim-configure</guid>
    <pubDate>Sat, 02 Apr 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>php stream扩展学习</title>
    <description>&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://php.net/manual/zh/intro.stream.php&quot;&gt;php stream extension manual &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://php.net/manual/zh/wrappers.php&quot;&gt;php支持的协议和封装协议&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://php.net/manual/zh/context.php&quot;&gt;上下文选项和参数&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;0-简介&quot;&gt;0. 简介&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;stream 扩展是PHP4.3.0版本发布出来的，用来泛华文件，网络等的操作。
stream可以简单的定义为一个资源对象,可以 提供一些流操作。
这个流可以读写，并且可以定位到流的任意位置(arbitrary location)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;既然是泛华了很多资源的操作，就需要有个封装来进行特定协议的解析和加密解密。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;比如HTTP相关的封装会实现从一个url转换成一个标准的http请求，发送到server端。&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;php支持对多种协议的封装，详情见&lt;a href=&quot;http://php.net/manual/zh/wrappers.php&quot;&gt;php支持的协议和封装协议&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;可以通过函数stream_get_wrappers()来获得PHP已经注册的相关协议的封装&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;可以通过函数stream_register_wrapper() 来注册一个协议的封装&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;我的机器&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stream_get_wrappers()&lt;/code&gt;的返回结果如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; $ php -r &quot;print_r(stream_get_wrappers());&quot;
Array
(
    [0] =&amp;gt; https
    [1] =&amp;gt; ftps
    [2] =&amp;gt; compress.zlib
    [3] =&amp;gt; compress.bzip2
    [4] =&amp;gt; php
    [5] =&amp;gt; file
    [6] =&amp;gt; glob
    [7] =&amp;gt; data
    [8] =&amp;gt; http
    [9] =&amp;gt; ftp
    [10] =&amp;gt; phar
    [11] =&amp;gt; zip
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;1-流过滤器stream-filters&quot;&gt;1. 流过滤器(stream filters)&lt;/h3&gt;

&lt;p&gt;对stream流上读或者写的数据做过滤,php所有支持的过滤器可以通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stream_get_filters()&lt;/code&gt;来获得，如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ php -r &quot;print_r(stream_get_filters());&quot;
Array
(
    [0] =&amp;gt; zlib.*
    [1] =&amp;gt; bzip2.*
    [2] =&amp;gt; convert.iconv.*
    [3] =&amp;gt; string.rot13
    [4] =&amp;gt; string.toupper
    [5] =&amp;gt; string.tolower
    [6] =&amp;gt; string.strip_tags
    [7] =&amp;gt; convert.*
    [8] =&amp;gt; consumed
    [9] =&amp;gt; dechunk
    [10] =&amp;gt; mcrypt.*
    [11] =&amp;gt; mdecrypt.*
    [12] =&amp;gt; http.*
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;每个过滤器实现不同的过滤功能&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;2-流的上下文-stream-contexts&quot;&gt;2. 流的上下文( stream contexts)&lt;/h3&gt;

&lt;p&gt;可以通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stream_context_create()&lt;/code&gt; 来创建流的上下文， 比如为fopen, file, file_get_contents等。
上下文包括http请求的header等. 各个协议都包含自己的上下文，详情参考&lt;a href=&quot;http://php.net/manual/zh/context.php&quot;&gt;上下文选项和参数&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;3-stream类函数&quot;&gt;3. stream类函数&lt;/h3&gt;

&lt;p&gt;详情参照&lt;a href=&quot;http://php.net/manual/zh/ref.stream.php&quot;&gt;PHP stream 函数&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;每个函数后续继续学习&lt;/p&gt;

&lt;p&gt;未完待续&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2016/03/31/php-stream-extension.html</link>
    <guid>http://huyongde.github.io/2016/03/31/php-stream-extension</guid>
    <pubDate>Thu, 31 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>php扩展操作相关的函数</title>
    <description>&lt;h3 id=&quot;简介&quot;&gt;简介&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;介绍PHP中操作扩展的 相关的函数如dl(), get_loaded_extensions(), get_extension_funcs()等&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;函数学习&quot;&gt;函数学习&lt;/h3&gt;

&lt;h4 id=&quot;1-dl&quot;&gt;1. dl()&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;说明 bool dl(string $library) 动态载入指定参数$library相关的扩展&lt;/li&gt;
  &lt;li&gt;参数  扩展的名称&lt;/li&gt;
  &lt;li&gt;返回值 成功返回true, 失败返回false;&lt;/li&gt;
  &lt;li&gt;例子&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;extension_loaded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'sqlite'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;strtoupper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;PHP_OS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'WIN'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;dl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'php_sqlite.dll'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;dl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'sqlite.so'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;2extension_loaded&quot;&gt;2.extension_loaded()&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;说明 bool extension_loaded(string $name)  检查一个扩展是否已经加载&lt;/li&gt;
  &lt;li&gt;参数  扩展的名称，可以通过php -m来得到所有的扩展的名称&lt;/li&gt;
  &lt;li&gt;返回值 扩展已经加载返回true,  否则返回false&lt;/li&gt;
  &lt;li&gt;例子 见 dl() 的例子&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;3-get_loaded_extensions&quot;&gt;3. get_loaded_extensions()&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;说明 array get_loaded_extensions([ bool $zend_extension]) 返回当前所有编译并加载的php扩展模块&lt;/li&gt;
  &lt;li&gt;参数 $zend_extension 为true只返回zend的扩展，默认是false, 返回所有扩展&lt;/li&gt;
  &lt;li&gt;返回值  返回所有扩展名组成的索引数组&lt;/li&gt;
  &lt;li&gt;例子  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print_r(get_loaded_extensions());&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;4-get_extension_funcs&quot;&gt;4. get_extension_funcs()&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;说明 array get_extension_funcs(string $module_name) 根据module_name返回扩展中所有定义的函数&lt;/li&gt;
  &lt;li&gt;参数 扩展模块的名字&lt;/li&gt;
  &lt;li&gt;返回值 模块内所有函数名组成的索引数组&lt;/li&gt;
  &lt;li&gt;例子 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;php -r &quot;print_r(get_extension_funcs('yaml'));&quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;get_extension_funcs() 可以用来初步的学习下一个扩展，获得这个扩展都实现了那些函数。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://php.net/manual/zh/ref.info.php&quot;&gt;php 选项信息函数&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    <link>http://huyongde.github.io/2016/03/29/php-extensions-funcs.html</link>
    <guid>http://huyongde.github.io/2016/03/29/php-extensions-funcs</guid>
    <pubDate>Tue, 29 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>php7 进行简单的php扩展开发</title>
    <description>&lt;h3 id=&quot;php扩展开发步骤&quot;&gt;php扩展开发步骤&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;用php-src/ext下面的php扩展骨架生成工具生成扩展的骨架，具体命令是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./ext_skel --extname=say&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;进行相关配置修改&lt;/li&gt;
  &lt;li&gt;修改扩展需要的c代码&lt;/li&gt;
  &lt;li&gt;运行phpize来生成编译扩展需要的configure&lt;/li&gt;
  &lt;li&gt;运行./configure&lt;/li&gt;
  &lt;li&gt;sudo make; sudo make install&lt;/li&gt;
  &lt;li&gt;修改php的配置文件，(通过php –ini查看配置文件位置), 添加extension=say.so&lt;/li&gt;
  &lt;li&gt;调用扩展定义的函数&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;##参考&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.bo56.com/php7%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8Bhello-word/&quot;&gt;php7 扩展开发&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2016/03/28/php7-ext.html</link>
    <guid>http://huyongde.github.io/2016/03/28/php7-ext</guid>
    <pubDate>Mon, 28 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>进程，线程，协程 学习比较</title>
    <description>&lt;p&gt;###参考&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868328689835ecd883d910145dfa8227b539725e5ed000&quot;&gt;廖雪峰协程介绍&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://tech.uc.cn/?p=1055&quot;&gt;UC 技术博客-协程实现基础&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.cnblogs.com/shenguanpu/archive/2013/05/05/3060616.html&quot;&gt;进程线程协程和goroutine那些事&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://segmentfault.com/a/1190000001813992#articleHeader28&quot;&gt;sf上七牛云介绍python中进程线程协程相关技术&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.csdn.net/gzlaiyonghao/article/details/5397038&quot;&gt;赖勇浩 协程介绍&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###相关知识汇总&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;协程可以认为是一种**用户态轻量级的线程**，操作系统是感知不到协程的存在的。
与系统提供的线程不同点是， 它需要主动让出CPU时间，而不是由系统进行调度，
即控制权在程序员手上,只需要进行用户态上下文切换。

既然看成是用户态线程，那必然要求程序员自己进行各个协程的调度，
这样就必须提供一种机制,供编写协程的人将当前协程挂起，即保存协程运行场景的一些数据，
调度器在其他协程挂起时再将此协程运行场景的数据恢复，以便继续运行。
这里我们将协程运行场景的数据称为上下文。

在linux里，有getcontext和swapcontext等接口来获取当前的上下文数据和切换上下文。
那如果没有提供相应的接口，又该如何来实现呢？

其实说到底，保存下上文数据，不外乎就是保存下当前运行的栈空间的数据，
还有cpu各个寄存器相应的值。只要我们能够将其保存下来，在特定的时刻恢复回去就可以了。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;###线程和协程的区别：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;一旦创建完线程，你就无法决定他什么时候获得时间片，什么时候让出时间片了，你把它交给了内核。
而协程编写者可以有一是可控的切换时机，二是很小的切换代价。
从操作系统有没有调度权上看，协程就是因为不需要进行内核态的切换，所以会使用它，
赖勇浩和dccmx 这个定义我觉得相对准确  &lt;strong&gt;协程是用户态的轻量级的线程&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;###进程、线程、协程比较&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;进程拥有自己独立的堆和栈，既不共享堆，亦不共享栈，进程由操作系统调度。&lt;/li&gt;
  &lt;li&gt;线程拥有自己独立的栈和共享的堆，共享堆，不共享栈，线程亦由操作系统调度(标准线程是的)。&lt;/li&gt;
  &lt;li&gt;协程和线程一样共享堆，不共享栈，协程由程序员在协程的代码里显示调度。&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;进程和其他两个的区别还是很明显的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;协程和线程的区别是：协程避免了无意义的调度，由此可以提高性能，但也因此，程序员必须自己承担调度的责任，&lt;/p&gt;

&lt;p&gt;同时，协程也失去了标准线程使用多CPU的能力, 但是可用通过多个(进程+多协程)模式来充分利用多CPU。&lt;/p&gt;

&lt;p&gt;###进程与线程的比较&lt;/p&gt;

&lt;p&gt;进程和线程的主要差别在于它们是不同的操作系统资源管理方式。
进程有独立的地址空间，一个进程崩溃后，在保护模式下不会对其它进程产生影响，
而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量，但线程之间没有单独的地址空间，
一个线程死掉就等于整个进程死掉，所以多进程的程序要比多线程的程序健壮 ，
但在进程切换时，耗费资源较大，效率要差一些。
但对于一些要求同时进行并且又要共享某些变量的并发操作，只能用线程，不能用进程&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2016/03/19/process-thread-coroutine.html</link>
    <guid>http://huyongde.github.io/2016/03/19/process-thread-coroutine</guid>
    <pubDate>Sat, 19 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>linux 服务器集群系统，LVS学习</title>
    <description>&lt;p&gt;###参考
本文参考章文嵩博士的&lt;a href=&quot;http://www.linuxvirtualserver.org/zh/lvs1.html&quot;&gt;LVS 服务器集群系统&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;###LVS 简介&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;LVS 是linux virtual server, 是通过一些手段，让服务可以承载大流量和大压力,  其中包括负载均衡技术和负载调度算法, 
下面介绍在第四层(传输层)上的负载均衡技术&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;###负载均衡技术&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;网络地址转换实现虚拟服务器(virtual server via Network Address Translation, VS/NAT), 通过网络地址（IP 和Port）转换，
调度器重写请求报文的目的地址(IP 和 port)，根据预设的调度算法,讲去请求分配给后端真实的服务器。后端真实服务器的响应报文经过调度器是，
报文的源地址被重写，再返回给客户端，完成整个负载调度过程。&lt;/li&gt;
  &lt;li&gt;IP隧道实现虚拟服务器(virtual server via IP Tunneling, VS/TUN) ， 采用NAT技术时，由于请求和响应报文都需要经过调度器进行地址重写，
当客户端的请求越来越多时，调度器的处理能力和网卡都可能成为瓶颈;为了解决这个问题，调度器把请求报文通过ip隧道转发给后端真实服务器，
真实服务器的响应报文直接发给客户端.这样调度器只需要处理请求报文.一般情况下，请求报文比响应报文小的多，才有IP TUN技术后，可以大大提高
系统的吞吐量。&lt;/li&gt;
  &lt;li&gt;直接路由实现虚拟服务器(Virtual Server Via Direct Routing, VS/DR), VS/DR 中，调度器通过修改请求报文的物理地址,将请求转发给真实服务器，
真实服务器的响应报文直接发给客户端。和IP 隧道技术一样DR可以大大提升系统吞吐量，但是要求调度器和真实服务器都有一个网卡连在同一个物理网段上。&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;如上简单介绍了三种IP层的负载均衡技术，详细的可以参考&lt;a href=&quot;http://www.linuxvirtualserver.org/zh/lvs3.html&quot;&gt;LVS中的负载均衡技术&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;###负载调度算法&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;轮叫(round Robin)&lt;/li&gt;
  &lt;li&gt;加权轮叫(Weighted Round Robin)&lt;/li&gt;
  &lt;li&gt;最少链接(Least Connections)&lt;/li&gt;
  &lt;li&gt;加权最少链接(Weighted Least Connections)&lt;/li&gt;
  &lt;li&gt;局部最少链接(Locality-Based Least Connections)&lt;/li&gt;
  &lt;li&gt;目标地址散列(destination hashing)&lt;/li&gt;
  &lt;li&gt;源地址散列(source hashing)&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;负载调度算法详情可以参考&lt;a href=&quot;http://www.linuxvirtualserver.org/zh/lvs4.html&quot;&gt;LVS的负载调度算法&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;###补充1&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;如上介绍的都是通过修改目的地址的IP和PORT来实现负载均衡的技术，是在第四层传输层实施的负载均衡技术;也可以在第七层应用层做负载均衡。
第四层和第七层有什么区别呢？&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;####第四层(传输层)负载均衡&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;传输层负载均衡技术，通过修改报文中的目标地址和端口，
再加上负载均衡设备设置的负载调度算法，
决定最终选择的真实服务器与请求客户端建立TCP连接,然后为客户端服务。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;####第七层(应用层)负载均衡&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;应用层负载均衡技术，是通过HTTP的URL或者其他的真正有意义的信息，
以及负载调度算法,决定最终的真实服务器。第七层负载均衡技术中的调度器其实就是代理服务器。
客户端要和七层负载均衡技术中的调度器进行三次握手，完成对应用层的数据解析，
然后调度器在和后端真实服务器进行三次握手，转发用户请求到真实服务器，
真实服务器的响应报文，也需要通过调度器返回给客户端。这里调度器就相当于一个代理服务器。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;####补充2&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;介绍下开放式系统互联七层网络模型和TCP/IP 五层网络模型&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;####OSI七层网络模型(Open System Interconnection, 开放式系统互联)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;应用层&lt;/li&gt;
  &lt;li&gt;表示层&lt;/li&gt;
  &lt;li&gt;会话层&lt;/li&gt;
  &lt;li&gt;传输层&lt;/li&gt;
  &lt;li&gt;网络层&lt;/li&gt;
  &lt;li&gt;数据链路层&lt;/li&gt;
  &lt;li&gt;物理层&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;从下到上，分别为第一层(物理层)，到第七层(应用层).&lt;/p&gt;

&lt;p&gt;####TCP/IP 五层网络模型&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;应用层&lt;/li&gt;
  &lt;li&gt;传输层&lt;/li&gt;
  &lt;li&gt;网络层&lt;/li&gt;
  &lt;li&gt;数据链路层&lt;/li&gt;
  &lt;li&gt;物理层&lt;/li&gt;
&lt;/ul&gt;

</description>
    <link>http://huyongde.github.io/2016/03/17/linux-virtual-server-lvs.html</link>
    <guid>http://huyongde.github.io/2016/03/17/linux-virtual-server-lvs</guid>
    <pubDate>Thu, 17 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>vim markdown语法高亮插件</title>
    <description>&lt;p&gt;&lt;a href=&quot;https://github.com/plasticboy/vim-markdown&quot;&gt;插件vim-markdown  github 主页&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;安装插件&quot;&gt;安装插件&lt;/h2&gt;

&lt;p&gt;安装直接添加如下plugin配置, 然后执行PluginInstall(前提是你已经安装了vim-Plugin)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Plugin 'godlygeek/tabular'
Plugin 'plasticboy/vim-markdown'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;其他配置&quot;&gt;其他配置&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let g:vim_markdown_folding_disabled = 1 &quot;&quot;&quot;&quot;设置不做代码折叠
let g:vim_markdown_frontmatter=1 &quot;&quot; 设置支持yaml语法
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;设置完后就可以愉快的在vim下写jekyll搭建的博客的文章了。&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2016/03/16/vim-markdown-plugin.html</link>
    <guid>http://huyongde.github.io/2016/03/16/vim-markdown-plugin</guid>
    <pubDate>Wed, 16 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>jekyll搭建github page 博客汇总</title>
    <description>&lt;p&gt;###搭建huyongde.github.io过程中总结的,和大家分享下&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;通过jekyll生成博客模板，并把博客迁移到github page上详情见&lt;a href=&quot;http://huyongde.github.io/2015/11/23/jekyll-learn.html&quot;&gt;jekyll 入门 &amp;amp;&amp;amp; jekyll 搭建github page的框架&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;####博客目前支持的功能&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://huyongde.github.io/tags/&quot;&gt;tags&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://huyongde.github.io/archives/&quot;&gt;archive&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;首页文章分页功能&lt;/li&gt;
  &lt;li&gt;访问pv,uv计数&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.clustrmaps.com/map/Huyongde.github.io&quot;&gt;访问者地理分布图&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://disqus.com&quot;&gt;disqus的评论系统&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;显示具有相同 tag的文章&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;####添加相关功能的方法&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://huyongde.github.io/2015/11/26/add-disqus-to-jekyll-for-comments.html&quot;&gt;为博客添加评论系统disqus&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://huyongde.github.io/2016/01/03/jekyll-tags-page.html&quot;&gt;添加tags页面&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://huyongde.github.io/2016/01/05/jekyll-archive.html&quot;&gt;添加archives归档页面&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://huyongde.github.io/2016/01/04/related-posts.html&quot;&gt;添加tag相同的相关文章功能&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://huyongde.github.io/2016/01/04/jekyll-paginate.html&quot;&gt;jekyll-paginate为博客首页添加分页功能&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;添加了如上功能之后，你就有了个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;博客虽小，五脏俱全&lt;/code&gt;的blog了。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;目前总结的就这么多，希望对大家有些帮助&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    <link>http://huyongde.github.io/2016/03/15/building-blog-summary.html</link>
    <guid>http://huyongde.github.io/2016/03/15/building-blog-summary</guid>
    <pubDate>Tue, 15 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>mac 安装php7</title>
    <description>&lt;p&gt;###homebrew&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The missing package manager for OS X&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;homebrew可以用来在mac上安装一些软件和库，比如mysql, nginx, redis等，它会把所需要的依赖给你自动安装。&lt;/p&gt;

&lt;p&gt;homebrew有基本的几个命令&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;brew install xxx&lt;/li&gt;
  &lt;li&gt;brew search xxx&lt;/li&gt;
  &lt;li&gt;brew update&lt;/li&gt;
  &lt;li&gt;brew unintall xxx&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;homebrew具体请参考官网&lt;a href=&quot;http://brew.sh/&quot;&gt;homebrew home&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;###brew来安装php&lt;/p&gt;

&lt;p&gt;安装命令是:&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew install homebrew/php/php70&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;安装过程中会遇到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configure: error: Cannot find libz&lt;/code&gt; 的错误，&lt;/p&gt;

&lt;p&gt;google了把，发现了个解决方案&lt;a href=&quot;http://codex16.com/mac-osx-brew-install-php56-cannot-find-libz/&quot;&gt;cannot find libz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;这个问题解决后，又出现了一个GD相关的错误，搞了会没搞定。&lt;/p&gt;

&lt;p&gt;###大招
**最后google出来一个安装方式&lt;a href=&quot;http://php-osx.liip.ch/&quot;&gt;MAC OS 一行代码安装php7&lt;/a&gt; **&lt;/p&gt;

&lt;p&gt;**安装方式是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -s http://php-osx.liip.ch/install.sh | bash -s 7.0&lt;/code&gt; **&lt;/p&gt;

&lt;p&gt;等待一段时间后，终于安装成功了，&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ 10:15上午 ]  [ huyongde@huyongde:/usr/local/php5/bin(master✔) ]
 $ ./php -v
PHP 7.0.4 (cli) (built: Mar 10 2016 14:34:46) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
    with Xdebug v2.4.0RC3, Copyright (c) 2002-2015, by Derick Rethans
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;建议先翻墙再执行命令。终于安装好了，迫不及待把玩一下php7.&lt;/p&gt;

&lt;p&gt;下面是PHP7相关配置的路径：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; $ ./php --ini
Configuration File (php.ini) Path: /usr/local/php5/lib
Loaded Configuration File:         /usr/local/php5/lib/php.ini
Scan for additional .ini files in: /usr/local/php5/php.d
Additional .ini files parsed:      /usr/local/php5/php.d/10-extension_dir.ini,
/usr/local/php5/php.d/20-extension-opcache.ini,
/usr/local/php5/php.d/50-extension-apcu.ini,
/usr/local/php5/php.d/50-extension-curl.ini,
/usr/local/php5/php.d/50-extension-gmp.ini,
/usr/local/php5/php.d/50-extension-imap.ini,
/usr/local/php5/php.d/50-extension-intl.ini,
/usr/local/php5/php.d/50-extension-mcrypt.ini,
/usr/local/php5/php.d/50-extension-mssql.ini,
/usr/local/php5/php.d/50-extension-pdo_pgsql.ini,
/usr/local/php5/php.d/50-extension-pgsql.ini,
/usr/local/php5/php.d/50-extension-propro.ini,
/usr/local/php5/php.d/50-extension-raphf.ini,
/usr/local/php5/php.d/50-extension-readline.ini,
/usr/local/php5/php.d/50-extension-xdebug.ini,
/usr/local/php5/php.d/50-extension-xsl.ini,
/usr/local/php5/php.d/60-extension-pecl_http.ini,
/usr/local/php5/php.d/99-liip-developer.ini
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;###配置让php7成为默认的php&lt;/p&gt;

&lt;p&gt;修改自己的系统配置，我用的是zsh，所以我在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.zshrc&lt;/code&gt;中添加了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export PATH=/usr/local/php5/bin:$PATH&lt;/code&gt; 这行代码，&lt;/p&gt;

&lt;p&gt;保存退出后，执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source ~/.zshrc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;现在直接命令行执行php就是php7了。&lt;/p&gt;

&lt;p&gt;####大功告成。&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2016/03/13/mac-install-php7-install.html</link>
    <guid>http://huyongde.github.io/2016/03/13/mac-install-php7-install</guid>
    <pubDate>Sun, 13 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>docker 入门学习</title>
    <description>&lt;blockquote&gt;
  &lt;p&gt;本文主要介绍如何在mac上安装docker，以及简单的把玩docker&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;###安装
docker官网&lt;a href=&quot;https://www.docker.com/&quot;&gt;docker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;官网提供的下载链接&lt;a href=&quot;https://github.com/docker/toolbox/releases/download/v1.10.3/DockerToolbox-1.10.3.pkg&quot;&gt;点击下载&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;从官网提供的github下载链接下载速度比较慢，可以去我分享的网盘&lt;a href=&quot;http://pan.baidu.com/s/1kUqexSV&quot;&gt;下载链接&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;下载完了之后一直下一步安装OK了。&lt;/p&gt;

&lt;p&gt;###把玩docker&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for i in &lt;/code&gt;docker ps -a&lt;/td&gt;
          &lt;td&gt;grep nginx&lt;/td&gt;
          &lt;td&gt;grep -v Up&lt;/td&gt;
          &lt;td&gt;awk ‘{print $1}’&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;; do docker rm $i;done&lt;/code&gt;  用来删除你用docker启动的所用的nginx服务&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for i in &lt;/code&gt;docker ps -a&lt;/td&gt;
          &lt;td&gt;grep Exited&lt;/td&gt;
          &lt;td&gt;awk ‘{print $1}’&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;;do echo $i; docker rm $i;done&lt;/code&gt;   删除所有你用docker运行过已经停止的服务，&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;未完待续&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2016/03/13/docker-%E5%85%A5%E9%97%A8.html</link>
    <guid>http://huyongde.github.io/2016/03/13/docker-入门</guid>
    <pubDate>Sun, 13 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>PHP性能之路</title>
    <description>&lt;p&gt;###PHP 性能之路&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;纵观语言发展历史，从0和1的机器码开始，到汇编语言，然后到C语言，再到动态脚本语言PHP。执行效率呈指数下降，但是，学习门槛也呈指数降低。PHP语言不仅屏蔽了C的内存&amp;gt; 管理和指针的复杂性，而且更进一步屏蔽了变量类型的复杂性。提升了项目开发的效率，降低了学习的门槛，但同时牺牲了一定的执行性能。然后，HHVM的Hack给我们一种“回归&amp;gt; 原始”的感觉，重新引入了变量的复杂性。当然，不同的语言解决不同场景下的问题，并不能够一概而论&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/image/php.jpg&quot; alt=&quot;二进制机器码到PHP&quot; /&gt;&lt;/p&gt;

&lt;p&gt;####前戏&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;95年php诞生，&lt;/li&gt;
  &lt;li&gt;php (personal home page)&lt;/li&gt;
  &lt;li&gt;81.9%的网站是PHP开发&lt;/li&gt;
  &lt;li&gt;php中1+”aaa” 结果是？&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;####正文&lt;/p&gt;

&lt;p&gt;性能所在点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;IO&lt;/li&gt;
  &lt;li&gt;memory&lt;/li&gt;
  &lt;li&gt;cpu&lt;/li&gt;
  &lt;li&gt;network&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PHP7&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;php7 又称 php next generation&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.php.net/phpng&quot;&gt;phpng&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;HHVM(hiphop virtual machine), HHVM提升PHP性能的途径，采用的方式就是替代Zend引擎来生成和执行PHP的中间&lt;strong&gt;字节码&lt;/strong&gt;（HHVM生成自己格式的中间字节码），执行时通过JIT（Just In Time，即时编译是种软件优化技术，指在运行时才会去编译字节码为机器码）转为&lt;strong&gt;机器码&lt;/strong&gt;执行。Zend引擎默认做法，是先编译为opcode，然后再逐条执行，通常每条指令对应的是C语言级别的函数。如果我们产生大量重复的opcode（纯PHP写的代码和函数），对应的则是Zend多次逐条执行这些C代码。而JIT所做的则是更进一步，将大量重复执行的字节码在运行的时候编译为机器码，达到提高执行效率的目的。通常，触发JIT的条件是代码或者函数被多次重复调用。&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.csdn.net/article/2014-12-25/2823234&quot;&gt;HHVM VS PHP7,优化PHP性能&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://hhvm.com/&quot;&gt;HHVM官网&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;fastercgi&lt;/li&gt;
  &lt;li&gt;php7 array 底层结构升级&lt;/li&gt;
  &lt;li&gt;JIT (just in time) : JIT（即时）编译器：即时编译是种软件优化技术，指在运行时才会去编译字节码。字节码会存放在内存中，然后JIT编译器会根据需要加载并编译所涉的字节码。&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2016/03/12/sf-performance-travel.html</link>
    <guid>http://huyongde.github.io/2016/03/12/sf-performance-travel</guid>
    <pubDate>Sat, 12 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>php 迭代器、yield、生成器以及协程</title>
    <description>&lt;p&gt;####参考&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.cnblogs.com/whoamme/p/5039533.html&quot;&gt;php生成器和协程实现&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.laruence.com/2015/05/28/3038.html&quot;&gt;在PHP中使用协程实现多任务调度(鸟哥)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://phphub.org/topics/1430&quot;&gt;php生成器和协程的实现&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###学习总结&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;迭代器的优点是在处理大量数据的时候不需要一次性全部加载到内存中.&lt;/li&gt;
  &lt;li&gt;协程是基于iterator, yield, generator 实现的.&lt;/li&gt;
  &lt;li&gt;有yield的函数就变成了一个generator.&lt;/li&gt;
  &lt;li&gt;yield返回的是一个iterator.&lt;/li&gt;
  &lt;li&gt;yield既可以返回也可以接收数据.&lt;/li&gt;
&lt;/ol&gt;
</description>
    <link>http://huyongde.github.io/2016/03/08/php-iterator-yield-generator-coroutine.html</link>
    <guid>http://huyongde.github.io/2016/03/08/php-iterator-yield-generator-coroutine</guid>
    <pubDate>Tue, 08 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>IO多路复用 (select, pool, epool)</title>
    <description>&lt;p&gt;###参考
作者：罗志宇
链接：https://www.zhihu.com/question/32163005/answer/55772739
来源：知乎
著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。&lt;/p&gt;

&lt;p&gt;###说明本文原文转载，主要是方便自己学习,原文出处见上面&lt;/p&gt;

&lt;p&gt;###正文&lt;/p&gt;

&lt;p&gt;假设你是一个机场的空管， 你需要管理到你机场的所有的航线， 包括进港，出港， 有些航班需要放到停机坪等待，有些航班需要去登机口接乘客。&lt;/p&gt;

&lt;p&gt;你会怎么做?&lt;/p&gt;

&lt;p&gt;最简单的做法，就是你去招一大批空管员，然后每人盯一架飞机， 从进港，接客，排位，出港，航线监控，直至交接给下一个空港，全程监控。&lt;/p&gt;

&lt;p&gt;那么问题就来了： 
很快你就发现空管塔里面聚集起来一大票的空管员，交通稍微繁忙一点，新的空管员就已经挤不进来了。 
空管员之间需要协调，屋子里面就1, 2个人的时候还好，几十号人以后 ，基本上就成菜市场了。
空管员经常需要更新一些公用的东西，比如起飞显示屏，比如下一个小时后的出港排期，最后你会很惊奇的发现，每个人的时间最后都花在了抢这些资源上。&lt;/p&gt;

&lt;p&gt;现实上我们的空管同时管几十架飞机稀松平常的事情， 他们怎么做的呢？ 
他们用这个东西 
这个东西叫flight progress strip. 每一个块代表一个航班，不同的槽代表不同的状态，然后一个空管员可以管理一组这样的块（一组航班），而他的工作，就是在航班信息有新的更新的时候，把对应的块放到不同的槽子里面。&lt;/p&gt;

&lt;p&gt;这个东西现在还没有淘汰哦，只是变成电子的了而已。。&lt;/p&gt;

&lt;p&gt;是不是觉得一下子效率高了很多，一个空管塔里可以调度的航线可以是前一种方法的几倍到几十倍。&lt;/p&gt;

&lt;p&gt;如果你把每一个航线当成一个Sock(I/O 流), 空管当成你的服务端Sock管理代码的话.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;第一种方法就是最传统的多进程并发模型 (&lt;strong&gt;每进来一个新的I/O流会分配一个新的进程管理&lt;/strong&gt;)&lt;/li&gt;
  &lt;li&gt;第二种方法就是I/O多路复用 (&lt;strong&gt;单个线程，通过记录跟踪每个I/O流(sock)的状态，来同时管理多个I/O流&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其实“I/O多路复用”这个坑爹翻译可能是这个概念在中文里面如此难理解的原因。所谓的I/O多路复用在英文中其实叫 I/O multiplexing. 如果你搜索multiplexing啥意思，基本上都会出这个图： 
于是大部分人都直接联想到”一根网线，多个sock复用” 这个概念，包括上面的几个回答， 其实不管你用多进程还是I/O多路复用， 网线都只有一根好伐。多个Sock复用一根网线这个功能是在内核＋驱动层实现的。&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;重要的事情再说一遍： I/O multiplexing 这里面的 multiplexing 指的其实是在单个线程通过记录跟踪每一个Sock(I/O流)的状态(对应空管塔里面的Fight progress strip槽)来同时管理多个I/O流. 发明它的原因，是尽量多的提高服务器的吞吐能力。
***&lt;/p&gt;

&lt;p&gt;是不是听起来好拗口，看个图就懂了.&lt;/p&gt;

&lt;p&gt;在同一个线程里面， 通过拨开关的方式，来同时传输多个I/O流， (学过EE的人现在可以站出来义正严辞说这个叫“时分复用”了）。&lt;/p&gt;

&lt;p&gt;什么，你还没有搞懂“一个请求到来了，nginx使用epoll接收请求的过程是怎样的”， 多看看这个图就了解了。提醒下，ngnix会有很多链接进来， epoll会把他们都监视起来，然后像拨开关一样，谁有数据就拨向谁，然后调用相应的代码处理。&lt;/p&gt;

&lt;p&gt;－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－&lt;/p&gt;

&lt;p&gt;了解这个基本的概念以后，其他的就很好解释了。&lt;/p&gt;

&lt;p&gt;####select, poll, epoll 都是I/O多路复用的具体的实现，之所以有这三个鬼存在，其实是他们出现是有先后顺序的。&lt;/p&gt;

&lt;h3 id=&quot;select&quot;&gt;select&lt;/h3&gt;

&lt;p&gt;I/O多路复用这个概念被提出来以后， select是第一个实现 (1983 左右在BSD里面实现的)。&lt;/p&gt;

&lt;p&gt;select 被实现以后，很快就暴露出了很多问题。 
select 会修改传入的参数数组，这个对于一个需要调用很多次的函数，是非常不友好的。
select 如果任何一个sock(I/O stream)出现了数据，select 仅仅会返回，但是并不会告诉你是那个sock上有数据，于是你只能自己一个一个的找，10几个sock可能还好，要是几万的sock每次都找一遍，这个无谓的开销就颇有海天盛筵的豪气了。
select 只能监视1024个链接， 这个跟草榴没啥关系哦，linux 定义在头文件中的，参见FD_SETSIZE。
select 不是线程安全的，如果你把一个sock加入到select, 然后突然另外一个线程发现，尼玛，这个sock不用，要收回。对不起，这个select 不支持的，如果你丧心病狂的竟然关掉这个sock, select的标准行为是。。呃。。不可预测的， 这个可是写在文档中的哦.
“If a file descriptor being monitored by select() is closed in another thread, the result is unspecified”
霸不霸气&lt;/p&gt;

&lt;h3 id=&quot;pool&quot;&gt;pool&lt;/h3&gt;
&lt;p&gt;于是14年以后(1997年）一帮人又实现了poll, poll 修复了select的很多问题，比如 
poll 去掉了1024个链接的限制，于是要多少链接呢， 主人你开心就好。
poll 从设计上来说，不再修改传入数组，不过这个要看你的平台了，所以行走江湖，还是小心为妙。
其实拖14年那么久也不是效率问题， 而是那个时代的硬件实在太弱，一台服务器处理1千多个链接简直就是神一样的存在了，select很长段时间已经满足需求。&lt;/p&gt;

&lt;p&gt;但是poll仍然不是线程安全的， 这就意味着，不管服务器有多强悍，你也只能在一个线程里面处理一组I/O流。你当然可以那多进程来配合了，不过然后你就有了多进程的各种问题。&lt;/p&gt;

&lt;h3 id=&quot;epool&quot;&gt;epool&lt;/h3&gt;
&lt;p&gt;于是5年以后, 在2002, 大神 Davide Libenzi 实现了epoll.&lt;/p&gt;

&lt;p&gt;epoll 可以说是I/O 多路复用最新的一个实现，epoll 修复了poll 和select绝大部分问题, 比如： 
epoll 现在是线程安全的。 
epoll 现在不仅告诉你sock组里面数据，还会告诉你具体哪个sock有数据，你不用自己去找了。&lt;/p&gt;

&lt;p&gt;epoll 当年的patch，现在还在，下面链接可以看得到：
/dev/epoll Home Page&lt;/p&gt;

&lt;p&gt;贴一张霸气的图，看看当年神一样的性能（测试代码都是死链了， 如果有人可以刨坟找出来，可以研究下细节怎么测的).&lt;/p&gt;

&lt;p&gt;横轴Dead connections 就是链接数的意思，叫这个名字只是它的测试工具叫deadcon. 纵轴是每秒处理请求的数量，你可以看到，epoll每秒处理请求的数量基本不会随着链接变多而下降的。poll 和/dev/poll 就很惨了。&lt;/p&gt;

&lt;p&gt;可是epoll 有个致命的缺点。。只有linux支持。比如BSD上面对应的实现是kqueue。&lt;/p&gt;

&lt;p&gt;其实有些国内知名厂商把epoll从安卓里面裁掉这种脑残的事情我会主动告诉你嘛。什么，你说没人用安卓做服务器，尼玛你是看不起p2p软件了啦。&lt;/p&gt;

&lt;p&gt;而ngnix 的设计原则里面， 它会使用目标平台上面最高效的I/O多路复用模型咯，所以才会有这个设置。一般情况下，如果可能的话，尽量都用epoll/kqueue吧。&lt;/p&gt;

&lt;p&gt;详细的在这里:
Connection processing methods&lt;/p&gt;

&lt;p&gt;PS: 上面所有这些比较分析，都建立在大并发下面，如果你的并发数太少，用哪个，其实都没有区别。 如果像是在欧朋数据中心里面的转码服务器那种动不动就是几万几十万的并发，不用epoll我可以直接去撞墙了。&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2016/03/07/select-pool-epool-2.html</link>
    <guid>http://huyongde.github.io/2016/03/07/select-pool-epool-2</guid>
    <pubDate>Mon, 07 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>学习redisbook, 了解redis设计和原理</title>
    <description>&lt;h3 id=&quot;redisbook介绍&quot;&gt;redisbook介绍&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;redisbook是huangjianhong大神写的，介绍redis设计和实现的一本，redis入门提高很好的一本书。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;相关学习资源&quot;&gt;相关学习资源&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/huangz1990/redis-3.0-annotated&quot;&gt;带注释的redis源码&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;redisbook.com&quot;&gt;redisbook网站&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://pan.baidu.com/s/1jGXhgvs&quot;&gt;redis pdf 版本下载&lt;/a&gt;  pdf版本已经大概看了一遍，确实对redis设计以及底层实现有了一些了解.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;目录&quot;&gt;目录&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;内部数据结构
    &lt;ul&gt;
      &lt;li&gt;sds&lt;/li&gt;
      &lt;li&gt;双端链表&lt;/li&gt;
      &lt;li&gt;字典&lt;/li&gt;
      &lt;li&gt;跳跃表&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;内存数据结构
    &lt;ul&gt;
      &lt;li&gt;intset，整数集合&lt;/li&gt;
      &lt;li&gt;压缩列表&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Redis数据类型
    &lt;ul&gt;
      &lt;li&gt;字符串&lt;/li&gt;
      &lt;li&gt;哈希表&lt;/li&gt;
      &lt;li&gt;列表&lt;/li&gt;
      &lt;li&gt;集合&lt;/li&gt;
      &lt;li&gt;有序集合&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;功能实现
    &lt;ul&gt;
      &lt;li&gt;事务&lt;/li&gt;
      &lt;li&gt;订阅发布&lt;/li&gt;
      &lt;li&gt;lua 脚本&lt;/li&gt;
      &lt;li&gt;慢查询日志&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;过期淘汰&lt;/li&gt;
  &lt;li&gt;持久化&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;redisbook学习心得&quot;&gt;redisbook学习心得&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;p&gt;逼迫自己静下心来做自己抵触的事情，一定会有收获的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;redis内部数据结构&quot;&gt;redis内部数据结构&lt;/h2&gt;

&lt;h3 id=&quot;0简单动态字符串simple-dynamic-string-sds&quot;&gt;0.简单动态字符串(simple dynamic string, sds)&lt;/h3&gt;
&lt;h4 id=&quot;redis-sds-的实现如下&quot;&gt;redis sds 的实现如下：&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;sdshdr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// buf已用长度&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// buf可用的长度&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//实际存储字符串数据的地方&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;基于如上sds的实现redis字符串有如下特征&quot;&gt;基于如上sds的实现，redis字符串有如下特征：&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;redis的字符串是使用sds来表示的，而不是c字符串&lt;/li&gt;
  &lt;li&gt;和 c字符串比较，sds有以下特性：
    &lt;ul&gt;
      &lt;li&gt;高效地获得字符串长度,O(1)&lt;/li&gt;
      &lt;li&gt;高效的执行追加操作&lt;/li&gt;
      &lt;li&gt;二进制安全&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;sds为追加操作进行追加优化，加快追加操作的速度，降低内存分配的次数，代价是多占用一些内存，而且这些内存不会主动释放&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;1双端列表&quot;&gt;1.双端列表&lt;/h3&gt;

&lt;h4 id=&quot;双端链表的实现&quot;&gt;双端链表的实现&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;//双端链表的节点&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;listNode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//前驱节点&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;listNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//后驱节点&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;listNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//值&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//双端链表的定义&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//表头指针&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;listNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//表尾指针&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;listNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 节点数量&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//复制函数&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//释放函数&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//比较函数&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
       
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;基于如上双端列表的实现双端链表有如下特征&quot;&gt;基于如上双端列表的实现，双端链表有如下特征：&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;链表带有前后驱的节点的指针，访问前后驱节点的负责度为O(1),并且链表可以进行两个方向上的迭代。&lt;/li&gt;
  &lt;li&gt;链表带有前后驱节点的指针，在头或者尾进行增加或者删除节点的复杂度为O(1).&lt;/li&gt;
  &lt;li&gt;链表带有记录链表长度的字段，可以O(1)获得链表的长度&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2字典&quot;&gt;2.字典&lt;/h3&gt;
&lt;blockquote&gt;
  &lt;p&gt;字典实现有多种方式，元素个数不多时，可以通过链表和数组来实现；元素个数达到一定数量级后可以考虑哈希表;还有一种更为复杂的平衡树实现。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;字典的hash表实现&quot;&gt;字典的hash表实现&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;//每个字典有两个hash表，来实现渐进式rehash&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;dict&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//特定类型的处理函数&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dictType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//类型处理函数的私有数据&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privdata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//哈希表2个&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dictht&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ht&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 记录rehash进度&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rehashidx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//迭代器的数量&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//哈希表的实现&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;dictht&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//哈希表节点指针的数组&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dictEntry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//指针数组的大小&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//指针数组的长度掩码,用来计算索引值&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sizemark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//哈希表现有节点数量&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;used&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dictht&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//table元素是个数组，数组中每个元素指向dictEntry结构体的指针。&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//hash表节点的结构体&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;dictEntry&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//键&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//值&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;    
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//后继节点&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dictEntry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dictEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//next属性指向另一个dictEntry节点，dictht是通过链地址来解决hash碰撞。&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//当不同的键有相同的hash值时，dictht通过一个链表来链接起来这些key-value对的dictEntry。&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;redis字典的实现可以用下图表示&quot;&gt;redis字典的实现可以用下图表示&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/image/redis-dict.png&quot; alt=&quot;redis-dict&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;字典的特征&quot;&gt;字典的特征&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;字典是由键值对构成的抽象的数据类型&lt;/li&gt;
  &lt;li&gt;Redis 中的数据库和哈希键都基于字典来实现&lt;/li&gt;
  &lt;li&gt;Redis 字典的底层实现为哈希表，每个字典有两个hash表，一般情况下只使用0号哈希表，只有在rehash进行时，才会同时使用0号和1号哈希表。&lt;/li&gt;
  &lt;li&gt;哈希表是使用链地址的方式来解决键冲突的问题&lt;/li&gt;
  &lt;li&gt;Rehash 可以用于扩展或收缩哈希表&lt;/li&gt;
  &lt;li&gt;对哈希表进行rehash，是分多次，渐进式完成的&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;3跳跃表&quot;&gt;3.跳跃表&lt;/h3&gt;

&lt;h4 id=&quot;30-参考&quot;&gt;3.0 参考&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;* [跳跃表](http://blog.sina.com.cn/s/blog_60707c0f0100wudj.html)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;31-跳跃表中查找元素时间复杂度ologn&quot;&gt;3.1 跳跃表中查找元素时间复杂度O(logN):&lt;/h4&gt;

&lt;p&gt;在跳跃表中查找一个元素x，按照如下几个步骤进行：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;从最上层的链的开头开始假设当前位置为p，它向右指向的节点为q（p与q不一定相邻），且q的值为y。
将y与x作比较: 如果x=y，输出查询成功，输出相关信息；
如果x大于y，从p向右移动到q的位置；
如果x小于y，从p向下移动一格， 如果当前位置在最底层的链S0中，且还要往下移动的话，则输出查询失败。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;32跳跃表的结构定义&quot;&gt;3.2跳跃表的结构定义&lt;/h4&gt;

&lt;p&gt;如下zskiplist和zskiplistNode定义都在redis.h头文件中.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zskiplist&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;zskiplistNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zskiplist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zskiplistNode&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;robj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;robj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;score&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zskiplistNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;backward&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zkiplistlevel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zskiplistNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;forward&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//跨越节点的数量&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zskiplistNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;blockquote&gt;
  &lt;p&gt;跳跃表中各节点是按照value来有序存储的，所以跳跃表的删除、插入、查找一个元素的时间复杂度都是O(logN).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;内存数据结构&quot;&gt;内存数据结构&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;虽然内部数据结构足够强大，但是创建一套完整的数据结构本身就是一套非常费内存的工作， 当一个对象包含的元素并不多,或者元素体积并不大时，使用代价高昂的内部数据结构并不是最好的办法&lt;/li&gt;
  &lt;li&gt;为了解决如上问题，redis在特定条件下会使用内存数据结构。&lt;/li&gt;
  &lt;li&gt;内存映射数据结构是一系列特殊编码的字节序列，创建他们所需要的内存通常比左右类似的内部数据结构要少的多，使用得当可以节省大量内存。&lt;/li&gt;
  &lt;li&gt;但是内存数据结构的编码方式比内部数据结构的要复杂，所以内存数据结构所占用的CPU 时间会比作用类似的内部数据结构要多。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Redis中内存映射数据结构有两种1.intset, 2.压缩列表&lt;/p&gt;

&lt;h3 id=&quot;1-整数集合&quot;&gt;1. 整数集合&lt;/h3&gt;
&lt;blockquote&gt;
  &lt;p&gt;整数集合用来保存有序、无重复的多个整数值，它会根据元素的值，自动想选择该用什么长度的整形类型来保存数据,是用最长类型元素的类型来保存所有的元素，
新元素的加入可能会改变整数集合的编码类型，可能要变成更大空间的类型来存储所有的元素&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;整数集合的数据结构&quot;&gt;整数集合的数据结构&lt;/h4&gt;

&lt;p&gt;定义在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intset.h&lt;/code&gt;中可以找到，详细如下：&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;intset&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//保存元素所使用的类型的长度&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//整数集合中元素个数&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//保存元素的数组&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;intset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;encoding&lt;/code&gt;的值可以是如下三种的一种：&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;err&quot;&gt;\#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INTSET_ENC_INT16&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int16_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;\#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INTSET_ENC_INT32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int32_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;\#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INTSET_ENC_INT64&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int64_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contents&lt;/code&gt; 是实际存放元素的地方，数组中的元素有如下两个特性：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;没有重复元素&lt;/li&gt;
  &lt;li&gt;元素在数组中从小到大排序。&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;intset-特征总结&quot;&gt;intset 特征总结&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;intset 用来存储有序、不重复的整形数据，它会根据元素的值，选择该用什么长度的整数类型来保存元素&lt;/li&gt;
  &lt;li&gt;当一个位长度更长的整数值添加到intset时，需要对intset进行升级,升级后的intset中的元素的位长度都等于新加元素的位长度,但元素值保持不变。&lt;/li&gt;
  &lt;li&gt;升级涉及对每个元素进行内存重分配和移动，时间复杂度是O(N)&lt;/li&gt;
  &lt;li&gt;intset是有序的，使用二分法来查找元素，时间复杂度O(logN)
    &lt;h3 id=&quot;2-压缩列表&quot;&gt;2. 压缩列表&lt;/h3&gt;
    &lt;blockquote&gt;
      &lt;p&gt;ziplist是一系列特殊编码的内存块构成的列表，一个ziplist可以包括多个节点entry，每个节点可以保存一个长度受限制的 字符数据或者整数.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;2-ziplist的结构&quot;&gt;2. ziplist的结构&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/image/ziplist.png&quot; alt=&quot;ziplist&quot; /&gt;&lt;/p&gt;

&lt;p&gt;下面分别解释途中每个字段的含义：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;zlbytes: uint32_t 表示整个ziplist的字节数，用来重新分配内存或者计算末端使用&lt;/li&gt;
  &lt;li&gt;zltail: uint32_t 到达整个ziplist表尾的偏移量，通过这个偏移量可以在不遍历整个列表的前提下，获得表尾节点&lt;/li&gt;
  &lt;li&gt;zllen: uint16_t ziplist中节点(entry)的数量&lt;/li&gt;
  &lt;li&gt;entryX : 节点，entry的结构见下图&lt;/li&gt;
  &lt;li&gt;zlend: uint8_t 用来标记ziplist末端&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/image/ziplistentry.png&quot; alt=&quot;ziplistentry&quot; /&gt;&lt;/p&gt;

&lt;p&gt;下面介绍些ziplist节点每个字段的含义：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;pre_entry_length: 上一个节点的长度，通过这个值，可以进行指针计算,从而跳到上一个节点&lt;/li&gt;
  &lt;li&gt;encoding &amp;amp;&amp;amp; length: encoding 和length共同决定了content中保存数据的数据类型以及长度。&lt;/li&gt;
  &lt;li&gt;content: 是节点的实际数据内容&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;ziplist总结&quot;&gt;ziplist总结&lt;/h3&gt;
&lt;blockquote&gt;
  &lt;p&gt;添加或者删除ziplist节点,可能会引起连锁更新，最坏时间复杂度是O(N^2), 不过连锁更新的概率不高，所以一般时间复杂度是O(N).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;redis-数据类型&quot;&gt;Redis 数据类型&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;p&gt;Redis中每个数据类型的对象都应该有个类型信息，并且redis每个数据类型的底层实现也有多种，实现方式在redis称为编码(encoding)方式,
 比如集合可以用intset或者hash表两种底层实现方式(编码方式).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;类型系统应该包括如下功能&quot;&gt;类型系统应该包括如下功能：&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;检查数据类型&lt;/li&gt;
  &lt;li&gt;检查数据编码(encoding)方式&lt;/li&gt;
  &lt;li&gt;数据所占空间分配，销毁和分享等&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;0-redisobject-定义&quot;&gt;0. RedisObject 定义&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;typedef struct redisObject {
    unsigned type:4; //对象类型
    unsigned encoding:4; //编码方式
    unsigned lru:24;  //LRU
    int refcount; //引用计数
    void *ptr; //指向robj对象对应的值
}robj;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中， type是对象类型，可以有如下5种类型:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define REDIS_STRING 0
#define REDIS_LIST 1
#define REDIS_SET 2
#define REDIS_ZSET 3
#define REDIS_HASH 4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;encoding 记录了对象的编码方式,可以有如下编码方式:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/* Objects encoding. Some kind of objects like Strings and Hashes can be
 * internally represented in multiple ways. The 'encoding' field of the object
 *  * is set to one of this fields for this object.
 *  */
#define REDIS_ENCODING_RAW 0     /* Raw representation */
#define REDIS_ENCODING_INT 1     /* Encoded as integer */
#define REDIS_ENCODING_HT 2      /* Encoded as hash table */
#define REDIS_ENCODING_ZIPMAP 3  /* Encoded as zipmap */
#define REDIS_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */
#define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define REDIS_ENCODING_INTSET 6  /* Encoded as intset */
#define REDIS_ENCODING_SKIPLIST 7  /* Encoded as skiplist */
#define REDIS_ENCODING_EMBSTR 8  /* Embedded sds string encoding */
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;ptr指向这个对象实际包括的值，如一个字典，一个列表，一个集合等。&lt;/p&gt;

&lt;p&gt;通过下图给出redisObject中类型和编码的关系:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/redisObject.png&quot; alt=&quot;redisObject&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;redis执行一个处理数据类型的命令需要进行如下步骤&quot;&gt;redis执行一个处理数据类型的命令需要进行如下步骤:&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;根据key在数据库的key空间中(数据库字典)中查找对应的RedisObject,如果没有找到则返回NULL.&lt;/li&gt;
  &lt;li&gt;检查RedisObject 的type属性，判断执行的命令是否和robj的类型相符合，若不符合，则返回类型错误.&lt;/li&gt;
  &lt;li&gt;根据redisObject encoding编码信息，选择合适的操作函数来处理底层数据结构.&lt;/li&gt;
  &lt;li&gt;数据结构操作的结果作为命令的返回值&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;redis引用计数以及对象销毁机制&quot;&gt;redis引用计数以及对象销毁机制&lt;/h4&gt;
&lt;blockquote&gt;
  &lt;p&gt;Redis的对象系统使用引用计数技术来负责维持和销毁对象，引用计数技术的机制如下：&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;每个redisObject 都有个refcount属性，指示这个对象被引用了多少次。&lt;/li&gt;
  &lt;li&gt;当创建一个redisObject时，refcount 设置为1.&lt;/li&gt;
  &lt;li&gt;当对一个对象进行共享时，它的refcount属性的值增加1.&lt;/li&gt;
  &lt;li&gt;当用完一个对象或者取消对一个对象的共享时，对象的refcount减小1.&lt;/li&gt;
  &lt;li&gt;当对象的refcount变为0时，这个redisObject结构,以及它所引用的数据结构的内存都将被释放。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;1数据类型字符串--redis_string&quot;&gt;1.数据类型—字符串  REDIS_STRING&lt;/h3&gt;

&lt;p&gt;RedisObject 字符串类型有两种编码格式REDIS_ENCODING_RAW 和 REDIS_ENCODING_INT，&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;REDIS_ENCODING_INT 用来保存long类型值&lt;/li&gt;
  &lt;li&gt;REDIS_ENCODING_RAW 使用sds来保存字符串、long long、double以及long double.
    &lt;blockquote&gt;
      &lt;p&gt;Redis为字符串类型选择的编码默认是REDIS_ENCODING_RAW。&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2数据类型哈希表--redis_hash&quot;&gt;2.数据类型—哈希表  REDIS_HASH&lt;/h3&gt;
&lt;p&gt;RedisObject 哈希表类型也有两种编码方式，REDIS_ENCODING_ZIPLIST 和 REDIS_ENCODING_HT&lt;/p&gt;

&lt;p&gt;Redis_HASH 的默认编码类型是REDIS_ENCODING_ZIPLIST(压缩列表),当如下两个条件满足任一个时，编码从REDIS_ENCODING_ZIPLIST
切换到REDIS_ENCODING_HT:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;哈希表中某个键或者某个值的长度大于server.hash_max_ziplist_value （默认是64字节）。&lt;/li&gt;
  &lt;li&gt;压缩列表中节点数量大于server.hash_max_ziplist_entries （默认是512）。&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;ZIPLIST来存储哈希表时,Key-Value是顺序存储的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;3数据类型列表----redis_list&quot;&gt;3.数据类型—列表    REDIS_LIST&lt;/h3&gt;
&lt;p&gt;RedisObject 列表类型也有两种编码方式压缩列表REDIS_ENCODING_ZIPLIST 和 双端列表REDIS_ENCODING_LINKEDLIST&lt;/p&gt;

&lt;p&gt;编码选择:创建一个列表时，默认的编码方式是: REDIS_ENCODING_ZIPLIST压缩列表， 当下列某一个条件满足时，列表编码方式会切换成
REDIS_ENCODING_LINKEDLIST双端列表：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;试图向列表中插入一个字符串值，且这个字符串长度超过server.list_max_ziplist_value(默认是64字节);&lt;/li&gt;
  &lt;li&gt;ziplist包含节点超过server.list_max_ziplist_entries(默认是512)。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;4数据类型集合----redis_set&quot;&gt;4.数据类型—集合    REDIS_SET&lt;/h3&gt;
&lt;p&gt;RedisObject 集合类型有两种编码方式:REDIS_ENCODING_INTSET（整数集合）和 REDIS_ENCODING_HT（字典）&lt;/p&gt;

&lt;h4 id=&quot;编码选择&quot;&gt;编码选择&lt;/h4&gt;
&lt;p&gt;第一个添加到集合中的元素,决定了创建集合的编码:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;若的第一个元素可以表示为long long 整数类型，那么集合初始编码类型是REDIS_ENCODING_INTSET&lt;/li&gt;
  &lt;li&gt;否则，集合的编码类型为REDIS_ENCODING_HT（字典）&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;编码切换&quot;&gt;编码切换&lt;/h4&gt;
&lt;p&gt;如果集合用REDIS_ENCODING_INTSET编码，那么当下面任一个条件满足时，编码类型都会转换为REDIS_ENCODING_HT&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;intset 保存的整数的个数超过了server.set_max_intset_entries(默认是512).&lt;/li&gt;
  &lt;li&gt;试图往集合里面加一个新元素，并且这个新元素不能被long long类型表示时（也就是新元素不是整数时）。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;5数据类型有序集合-redis_zset&quot;&gt;5.数据类型—有序集合 REDIS_ZSET&lt;/h3&gt;
&lt;p&gt;RedisObject 有序集类型有两种编码方式，一种是压缩列表REDIS_ENCODING_ZIPLIST， 一种是通过skiplist跳跃表和字典共同实现。&lt;/p&gt;

&lt;h4 id=&quot;编码选择-1&quot;&gt;编码选择&lt;/h4&gt;
&lt;p&gt;zadd添加一个元素到一个空的有序集时，如果有序集同时满足如下条件，则用REDIS_ENCODING_ZIPLIST编码方式:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;服务器属性server.zset_ziplist_max_entries的值大于0(默认是128)&lt;/li&gt;
  &lt;li&gt;新元素的值小于server.zset_ziplist_max_value的值，默认是64字节&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;编码切换-1&quot;&gt;编码切换&lt;/h4&gt;
&lt;p&gt;对于一个压缩列表编码的有序集，若满足如下任一个条件，则有序集的编码转换为跳跃表和字典编码方式：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;ziplist压缩列表所保存的元素个数超过了server.zset_ziplist_max_entries的值，默认是128&lt;/li&gt;
  &lt;li&gt;新添加的元素的member的长度大于服务器属性server.zset_ziplist_max_value的值，默认是64字节。&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;有序集通过字典来实现通过key查找的O(1)复杂度， 用跳跃表来保证按照score查找的O(logN)的复杂度.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;四功能实现&quot;&gt;四、功能实现&lt;/h3&gt;

&lt;h4 id=&quot;1-事务&quot;&gt;1. 事务&lt;/h4&gt;
&lt;blockquote&gt;
  &lt;p&gt;redis 通过mutil discard exec 和 watch来实现事务操作。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;一个完整的事务包括&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;开始事务(multi), 执行mutil之后redis客户端的redis_multi选项打开，客户端从非事务状态转化为事务状态。&lt;/li&gt;
  &lt;li&gt;命令入队， 非事务状态的客户端发送给server的命令会被立即执行并返回执行结果；事务状态的客户端发送给server的命令会被加入事务队列，并返回&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QUEUED&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;执行事务(exec), 事务队列是一个数组，每个数组元素都包含三个属性：要执行的命令，命令的参数，命令参数的个数。执行事务阶段会根据FIFO来执行事务队列中的命令,执行每个命令的结果加入回复队列中,所有命令执行完后，把回复队列的结果返回给客户端。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;另外两个事务相关的命令&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;discard, discard命令用于取消事务，它清空客户端相关的整个事务队列，然后将客户端从事务状态调整到非事务状态，最后返回字符串OK给客户端，说明事务取消成功。&lt;/li&gt;
  &lt;li&gt;watch, watch 只能在客户端进入事务状态之前执行，来监视任意数量的键，当调用exec时，如果任意一个被监视的键，被其他客户端修改,那么整个事务不再执行，直接返回失败。&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;11watch-命令的实现&quot;&gt;1.1watch 命令的实现&lt;/h4&gt;

&lt;p&gt;每一个代表数据库的redis.h/redisDb数据结构中，都保存了一个watched_keys字典，字典的键就是被监视的键，
字典的值是一个链表，保存了那些客户端监视了这个键&lt;/p&gt;

&lt;p&gt;redisDb的数据结构如下:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;redisDb&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;//redis数据库的见空间&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 设置有效期的key的一个字典&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blocking_keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 处于堵塞状态的键&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ready_keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//被堵塞，但已经有数据的键&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;watched_keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 事务前被监视的键&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;evictionPoolEntry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eviction_pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* Eviction pool of keys */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//数据库编号&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;avg_ttl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//平均有效期，统计用的&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;redisDb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;12-wacth-命令的触发&quot;&gt;1.2 wacth 命令的触发&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;在任何对数据库的键空间进行修改的命令执行成功之后，multi/touchWatchKey函数都会被调用, touchWatchKey函数会检查数据库的
watched_keys字典，看是否有客户端在监听被本命令修改的键，如果有的话，程序会将所有监视被修改键的客户端的redis_dirty_cas选项打开.&lt;/li&gt;
  &lt;li&gt;当客户端发送exec执行事务时，服务器会对客户端的redis_dirty_cas选项做检查
    &lt;ul&gt;
      &lt;li&gt;如何客户端的redis_dirty_cas选项已经被打开，那说明客户端监视的键至少有一个已经被修改，事务的安全性已经被破坏。
服务器会停止执行此事务，直接向客户端返回空，表示事务执行失败。&lt;/li&gt;
      &lt;li&gt;如果客户端的redis_dirty_case选项未被打开，说明被客户端监视的key都是安全的，正常执行事务。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;13-事务的acid性质&quot;&gt;1.3 事务的ACID性质&lt;/h4&gt;

&lt;p&gt;传统的关系型数据库中，常用ACID性质来检查事务功能的安全性&lt;/p&gt;

&lt;p&gt;redis事务保证了其中的一致性(C)和隔离性(I), 但不保证原子性(A)和持久性(D)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;原子性(Atomicity) Redis单个命令的执行时原子的，但是redis没有在事务上增加任何维护原子性的机制，所以redis事务不是原子的。
  事务中所有命令执行成功则事务执行成功，但是若redis执行事务命令过程中被杀，它不提供事务中已执行命令的回滚操作。&lt;/li&gt;
  &lt;li&gt;一致性(Consistency) 根据持久化的rdb或者aof文件恢复到Redis内存中，数据和之前是一致的，所以Redis保证了一致性。&lt;/li&gt;
  &lt;li&gt;隔离性(Isolation) Redis是单进程程序，可以保证事务执行过程中不会被中断。&lt;/li&gt;
  &lt;li&gt;持久性(Durability), 即使有redis有rdb 和aof的持久化，但是两种方式都不能保证持久化的完备性。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2-订阅和发布&quot;&gt;2. 订阅和发布&lt;/h3&gt;

&lt;h4 id=&quot;21-频道的订阅和信息发布&quot;&gt;2.1 频道的订阅和信息发布&lt;/h4&gt;

&lt;p&gt;subscribe 可以让客户端定义任意多个频道，每当有新信息发送到频道时，所有订阅次频道的客户端都会收到对应的信息。
 publish 可以发送一个信息到某个频道。&lt;/p&gt;

&lt;h4 id=&quot;211-subscribe--订阅频道&quot;&gt;2.1.1 subscribe  订阅频道&lt;/h4&gt;

&lt;p&gt;每个运行的Redis服务器都维护着一个redis.h/redisServer的结构体， redisServer中有个pubsub_channels字典。
这个字典保存了所有被订阅频道的信息, 其中，字典的键就是频道的名字，字典的值是一个链表，链表中保存了所有订阅这个频道的客户端。
当一个客户端调用subscribe时，程序就会把此客户端和pubsub_channels字典关联起来，把此客户端append到频道对应的列表中。&lt;/p&gt;

&lt;p&gt;redisServer 结构体的部分定义如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; struct redisServer {
    // ...
    dict *pubsub_channels;
    list *pubsub_patterns;
    // ...
 };

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;订阅一个频道的伪代码如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def SUBSCRIBE (client, channels):
    for channel in channels:
        redisServer.pubsub_channels[channel].append(client)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;212-publish-发布信息到频道&quot;&gt;2.1.2 publish 发布信息到频道&lt;/h4&gt;

&lt;p&gt;当调用publish channel message后，程序会定位到字典pubsub_channels中key为channel的元素，然后将信息发送给键channel对应的列表中的所有的客户端。&lt;/p&gt;

&lt;p&gt;发布信息到一个频道的伪代码如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def PUBLISH (channel, message):
    for client in pubsub_channels[channel]:
        send_message(client, message)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;unsubscribe可以取消对一个频道的订阅&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;22-模式的订阅和信息发布&quot;&gt;2.2 模式的订阅和信息发布&lt;/h4&gt;

&lt;h4 id=&quot;221-psubscribe-订阅模式&quot;&gt;2.2.1 psubscribe 订阅模式&lt;/h4&gt;

&lt;p&gt;redisServer.pubsub_patterns 是一个链表，里面存储了模式相关的信息。&lt;/p&gt;

&lt;p&gt;pubsub_patterns链表中每个元素都是一个redis.h/pubsubPattern结构体，定义如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;typedef struct pubsubPattern {
    RedisClient *client;
    robj *pattern;
}pubsubPattern;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中， client保存了订阅了此模式的客户端，pattern 保存了被订阅的模式.&lt;/p&gt;

&lt;p&gt;每次调用psubscribe 命令，程序都会创建一个包含客户端信息和被订阅的模式信息的pubsubPattern结构体，
并将此结构体添加到redisServer.pubsub_patterns链表中。&lt;/p&gt;

&lt;p&gt;订阅模式的伪代码实现如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def PSUBSCRIBE(client, pattern):
    pubsubPattern *tmp
    tmp-&amp;gt;client = client
    tmp-&amp;gt;pattern = pattern
    redisServer.pubsub_patterns.append(tmp)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;222-发送消息到模式和频道&quot;&gt;2.2.2 发送消息到模式和频道&lt;/h4&gt;

&lt;p&gt;多了可以订阅模式之后，publish发送一个消息后，不仅订阅频道的客户端可以收到消息，订阅了对应模式的客户端也会收到消息
完整的发布消息的实现如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def PUBLISH(channel, message);
    for client in redisServer.pubsub_channels[channel]:
        send_message(client, message)

    for pattern, client in redisServer.pubsub_patterns:
        if match(channel, pattern):
            send_message(client, message)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;punsubscribe 用于退订一个模式&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;43-lua脚本&quot;&gt;4.3 lua脚本&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://oldblog.antirez.com/post/redis-and-scripting.html&quot;&gt;redis作者介绍lua脚本&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;431-redis引入lua脚本的意义&quot;&gt;4.3.1 Redis引入Lua脚本的意义&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;减少网络开销。可以将多个请求通过脚本的形式一次发送，减少网络时延, 也可以通过pipeline来实现一次发送多个命令。&lt;/li&gt;
  &lt;li&gt;原子操作。如前面介绍的，redis事务不能保证原子性; redis会将整个脚本作为一个整体执行，中间不会被其他命令插入。因此在编写脚本的过程中无需担心会出现竞态条件，无需使用事务。&lt;/li&gt;
  &lt;li&gt;复用。客户端发送的脚步会永久存在redis中，这样，其他客户端可以复用这一脚本而不需要使用代码完成相同的逻辑。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;未完待续&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2016/03/06/redisbook-learn.html</link>
    <guid>http://huyongde.github.io/2016/03/06/redisbook-learn</guid>
    <pubDate>Sun, 06 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>如何获得手机4G或者3G网络的数据包</title>
    <description>&lt;p&gt;###思路&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;移动端建热点，电脑连接移动建的热点，然后通过电脑访问某个网页就可以抓到通过移动4G或者3G访问网页的数据包，就可以分析下载速度等的问题&lt;/p&gt;
&lt;/blockquote&gt;
</description>
    <link>http://huyongde.github.io/2016/03/04/mobile-network-packet-sniffer.html</link>
    <guid>http://huyongde.github.io/2016/03/04/mobile-network-packet-sniffer</guid>
    <pubDate>Fri, 04 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>golang 解析toml配置文件</title>
    <description>&lt;p&gt;#####golang代码如下：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package main

import (
    &quot;fmt&quot;

    &quot;github.com/BurntSushi/toml&quot;
)

func main() {
    str_toml := `[[conf]]
        [[conf.a1]]
        min = 10
        max = 10240
        [[conf.a2]]
        min = 5000
        max = 10240
        [[conf.a3]]
        &quot;xxxx.yyyy.com&quot;=[0 ,100]
        `
    type MinMax struct {
        Min int
        Max int
    }
    type OneLevelConf struct {
        A1 []MinMax
        A2 []MinMax
        A3 []map[string]([]int64)
    }

    type CONF struct {
        Conf []OneLevelConf
    }
    var Conf CONF
    _, err2 := toml.Decode(str_toml, &amp;amp;Conf)
    if err2 != nil {
        fmt.Println(&quot;decode failed, error: &quot;, err2)
    }
    fmt.Printf(&quot;decoded: %+v\n&quot;, Conf)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;代码输出结果：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;decoded: {Conf:[{A1:[{Min:10 Max:10240}] A2:[{Min:5000 Max:10240}] A3:[map[xxxx.yyyy.com:[0 100]]]}]} 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;golang toml解析的package 可以通过：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go get github.com/BurntSushi/toml&lt;/code&gt; 来安装&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;解析起来最大的问题就是在结构体的定义。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;未完待续&lt;/p&gt;

&lt;p&gt;####参考
&lt;a href=&quot;https://github.com/mojombo/toml&quot;&gt;toml github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://segmentfault.com/a/1190000000477752&quot;&gt;toml sf &lt;/a&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2016/03/02/golang-parse-toml.html</link>
    <guid>http://huyongde.github.io/2016/03/02/golang-parse-toml</guid>
    <pubDate>Wed, 02 Mar 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>检查当前svn路径下面修改的PHP文件是否有语法错误(以及其他小技巧)</title>
    <description>&lt;h4 id=&quot;1-检查修改的php代码是否有语法错误&quot;&gt;1. 检查修改的php代码是否有语法错误&lt;/h4&gt;

&lt;p&gt;一行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shell&lt;/code&gt;代码搞定，代码如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd $1;for i in `svn st | awk '$1==&quot;M&quot; || $1==&quot;A&quot;{print $2}'`; do php -l $i;done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;使用说明:$1是要检查的文件夹路径，借助php -l参数，来完成检查&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;2-批量添加文件下新添加的文件到svn&quot;&gt;2. 批量添加文件下新添加的文件到svn&lt;/h4&gt;

&lt;p&gt;同样是一行代码:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;svn add `svn st | grep -E &quot;^\?.*.php&quot; | awk '{print $2}' | xargs`
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
    <link>http://huyongde.github.io/2016/02/29/check-svn-M-syntax.html</link>
    <guid>http://huyongde.github.io/2016/02/29/check-svn-M-syntax</guid>
    <pubDate>Mon, 29 Feb 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>网站短连接生成原理</title>
    <description>&lt;h3 id=&quot;短连接生成的两种方式&quot;&gt;短连接生成的两种方式&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;目前我所了解的短链接生成有两种方式&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;完全基于压缩算法，这样可以不使用数据库，直接使用压缩解压即可。&lt;/li&gt;
  &lt;li&gt;基于数据库存储长短链接直接的对应关系。&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;第二种方法，需要把长连接对应到一个唯一ID，通过把唯一的ID转化为62位的字符串(26个小写字母，26个大写字母加0-9十个数字),
唯一的ID按照62求余，求余数对应的62进制的字符，再把每个对应的字符链接起来.短链接一般6位，这样就可以表示62的6次方个url,500亿左右。把生成的唯一ID，短连接和长连接存储在nosql或者mysql中。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5 id=&quot;唯一的id获取方式有以下几种&quot;&gt;唯一的ID获取方式有以下几种&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;长url的crc32&lt;/li&gt;
  &lt;li&gt;数据量不大的时候可以用mysql数据库自增&lt;/li&gt;
  &lt;li&gt;也可以用时间戳加随机数，加一些特定的前缀，然后在crc32,获得一个数字，&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;go实现longurl转化为shorturl-git链接&quot;&gt;go实现longurl转化为shorturl &lt;a href=&quot;https://github.com/huyongde/shorturl&quot;&gt;git链接&lt;/a&gt;&lt;/h3&gt;

</description>
    <link>http://huyongde.github.io/2016/02/27/short-url.html</link>
    <guid>http://huyongde.github.io/2016/02/27/short-url</guid>
    <pubDate>Sat, 27 Feb 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>redis主从复制介绍</title>
    <description>&lt;h3 id=&quot;简介&quot;&gt;简介&lt;/h3&gt;
&lt;p&gt;Redis的replication机制允许slave从master那里通过网络传输拷贝到完整的数据备份。具有以下特点：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;异步复制。从2.8版本开始，slave能不时地从master那里获取到数据。&lt;/li&gt;
  &lt;li&gt;允许单个master配置多个slave&lt;/li&gt;
  &lt;li&gt;slave允许其它slave连接到自己。一个slave除了可以连接master外，它还可以连接其它的slave。形成一个图状的架构。&lt;/li&gt;
  &lt;li&gt;master在进行replication时是非阻塞的，这意味着在replication期间，master依然能够处理客户端的请求。&lt;/li&gt;
  &lt;li&gt;slave在replication期间也是非阻塞的，也可以接受来自客户端的请求，但是它用的是之前的旧数据。
可以通过配置来决定slave是否在进行replication时用旧数据响应客户端的请求，如果配置为否，那么slave将会返回一个错误消息给客户端。不过当新的数据接收完全后，必须将新数据与旧数据替换，即删除旧数据，在替换数据的这个时间窗口内，slave将会拒绝客户端的请求和连接。&lt;/li&gt;
  &lt;li&gt;一般使用replication来可以实现扩展性，例如说，可以将多个slave配置为“只读”，或者是纯粹的数据冗余备份。&lt;/li&gt;
  &lt;li&gt;能够通过replication来避免master每次持久化时都将整个数据集持久化到硬盘中。只需把master配置为不进行持久化操作(把配置文件中save相关的配置项注释掉即可)，然后连接上一个slave，这个slave则被配置为不时地进行持久化操作的。
不过需要注意的是，在这个用例中，必须确保master不会自动启动,具体原因请继续看下面的内容。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;redis-master关闭持久化可能存在的问题&quot;&gt;redis master关闭持久化可能存在的问题&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;当有需要使用到replication机制时，一般都会强烈建议把master的持久化开关打开。即使为了避免持久化带来的延迟影响，不把持久化开关打开，那么也应该把master配置为不会自动启动的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;为了更好的解释不进行持久化的master为什么要关闭自动启动，请看下面的例子：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;假设我们有一个redis节点A，设置为master，并且关闭持久化功能，另外两个节点B和C是它的slave，并从A复制数据。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;如果A节点崩溃了导致所有的数据都丢失了，它会有重启系统来重启进程。
但是由于持久化功能被关闭了，所以即使它重启了，它的数据集是空的。
而B和C依然会通过replication机制从A复制数据，所以B和C会从A那里复制到一份空的数据集，
并用这份空的数据集将自己本身的非空的数据集替换掉。于是就相当于丢失了所有的数据。

即使使用一些HA工具，比如说sentinel来监控master-slaves集群，
也会发生上述的情形，因为master可能崩溃后迅速恢复。
速度太快而导致sentinel无法察觉到一个failure的发生。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;当数据的安全很重要、持久化开关被关闭并且有replication发生的时候，那么应该禁止实例的自启动。&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;redis主从复制replication的原理&quot;&gt;redis主从复制(replication)的原理&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;如果你为master配置了一个slave，不管这个slave是否是第一次连接上Master，它都会发送一个SYNC命令给master请求复制数据。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;master收到SYNC命令后，会在后台进行数据持久化，持久化期间，master会继续接收客户端的请求，它会把这些可能修改数据集的请求缓存在内存中。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;当持久化进行完毕以后，master会把这份数据集发送给slave，slave会把接收到的数据进行持久化，然后再加载到内存中。
然后，master再将之前缓存在内存中的命令发送给slave。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;当master与slave之间的连接由于某些原因而断开时，slave能够自动重连Master，
如果master收到了多个slave并发连接请求，&lt;strong&gt;它只会进行一次持久化，而不是一个连接一次，然后再把这一份持久化的数据发送给多个并发连接的slave。&lt;/strong&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;当master和slave断开重连后，一般都会对整份数据进行复制。但从redis2.8版本开始，支持部分复制。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;master-slave的部分复制&quot;&gt;master slave的部分复制&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;从2.8版本开始，slave与master能够在网络连接断开重连后只进行部分数据复制。
master会在其内存中创建一个复制流的等待队列，
master和它所有的slave都维护了复制的数据下标和master的进程id，
因此，当网络连接断开后，slave会请求master继续进行未完成的复制，
从所记录的数据下标开始。如果进程id变化了，或者数据下标不可用，那么将会进行一次全部数据的复制。

支持部分数据复制的命令是*PSYNC*

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;不需要持久化的replication&quot;&gt;不需要持久化的replication&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;一般情况下，一次复制需要将内存的数据写到硬盘中，再将数据从硬盘读进内存，再发送给slave。

对于速度比较慢的硬盘，这个操作会给master带来性能上的损失。
Redis2.8版本开始，实验性地加上了无硬盘复制的功能。
这个功能能将数据从内存中直接发送到slave，而不用经过硬盘的存储。
不过这个功能目前处于实验阶段，还未正式发布。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;其他&quot;&gt;其他&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;slaveof master_ip master_Port 来配置slave的master&lt;/li&gt;
  &lt;li&gt;repl-diskless-sync 来配置不需要持久化的replication&lt;/li&gt;
  &lt;li&gt;slave-read-only 来配置slave只读&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://daoluan.net/blog/2014/04/22/decode-redis-replication/&quot;&gt;深入剖析Redis主从复制&lt;/a&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2016/02/26/redis-master-slave-replication.html</link>
    <guid>http://huyongde.github.io/2016/02/26/redis-master-slave-replication</guid>
    <pubDate>Fri, 26 Feb 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>mysql innodb 事务日志ib_logfile</title>
    <description>&lt;p&gt;###简介&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;事务日志或称redo日志，在mysql中默认以ib_logfile0,ib_logfile1名称存在,
可以手工修改参数，调节开启几组日志来服务于当前mysql数据库,mysql采用顺序，
循环写方式，每开启一个事务时， 会把一些相关信息记录事务日志中
(记录对数据文件数据修改的物理位置或叫做偏移量);

作用:在系统崩溃重启时，作事务重做；在系统正常时，每次checkpoint时间点，
会将之前写入事务应用到数据文件中。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;###引入一个问题&lt;/p&gt;

&lt;p&gt;&lt;em&gt;**在m/s环境中,innodb写完ib_logfile后,服务异常关闭，会不会主库能用ib_logfile恢复数据，而
binlog没写导致从库同步时少少这个事务？从而导致主从不一致; **&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;####redo日志写入方式：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;ib_logfile写入当前事务更新数据，并标上事务准备trx_prepare&lt;/li&gt;
  &lt;li&gt;写入bin-log&lt;/li&gt;
  &lt;li&gt;ib_logfile当前事务提交提交trx_commit&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;####恢复方式:
&lt;em&gt;**如果ib_logfile已经写入事务准备,那么在恢复过程中，会依据bin-log中该事务是否存在恢复数据。 **&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;假设:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;结束后异常,因没有写入bin-log，从库不会同步这个事务，主库上，重启时，在恢复日志中这个
事务没有commit，即rollback这个事务.&lt;/li&gt;
  &lt;li&gt;结束后异常，这会bin-log已经写入，从库会同步这个事务。主库依据恢复日志和bin-log，也正常恢复此事务
综上描述:bin-log写入完成，主从会正常完成事务；bin-log没有写入，主从库rollback事务;不会出现主从库不一致问题.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;###相关参数（全局&amp;amp;静态）:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;innodb_log_buffer_size:事务日志缓存区,可设置1M~8M,默认8M,延迟事务日志写入磁盘,
把事务日志缓存区想象形如”漏斗”状,会不停向磁盘记录缓存的日志记录,而何时写入通过参数
innodb_flush_log_at_trx_commit控制,稍后解释,启用大的事务日志缓存,可以将完整运行大事
务日志，暂时存放在事务缓存区中,不必(事务提交前)写入磁盘保存,同时也起到节约磁盘空间占用;&lt;/li&gt;
  &lt;li&gt;innodb_log_file_size:控制事务日志ib_logfile的大小,范围5MB~4G；所有事务日志ib_logfile0+
ib_logfile1+..累加大小不能超过4G，事务日志大，checkpoint会少,节省磁盘IO，但是大的事务日
志意味着数据库crash时，恢复起来较慢.
引入问题:修改该参数大小，导致ib_logfile文件的大小和之前存在的文件大小不匹配
解决方式：在干净关闭数据库情况下，删除ib_logfile，而后重启数据库，会自行创建该文件;&lt;/li&gt;
  &lt;li&gt;innodb_log_files_in_group:DB中设置几组事务日志，默认是2；&lt;/li&gt;
  &lt;li&gt;innodb_log_group_home_dir:事务日志存放目录，不设置，ib_logfile0…存在在数据文件目录下&lt;/li&gt;
  &lt;li&gt;innodb_flush_log_at_trx_commit：控制事务日志何时写盘和刷盘，安全递增.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;*log_buffer: 事务缓存区
    * 0:每秒一次事务缓存区刷新到文件系统，同时文件系统到磁盘同步，但是事务提交时，不会触发log_buffer到文件系统同步；
    * 2:每次事务提交时,会把事务缓存区日志刷新到文件系统中去，且每秒文件系统到磁盘同步;
    * 1:每次事务提交时刷新到磁盘，最安全;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;log_buffer各值适用环境:
    &lt;ul&gt;
      &lt;li&gt;0:磁盘IO能力有限,安全方便较差,无复制或复制延迟可以接受，如日志性业务，mysql损坏丢失1s事务数据;&lt;/li&gt;
      &lt;li&gt;2:数据安全性有要求，可以丢失一点事务日志，复制延迟也可以接受，OS损坏时才可能丢失数据;&lt;/li&gt;
      &lt;li&gt;1:数据安全性要求非常高，且磁盘IO能力足够支持业务，如充值消费，敏感业务;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

</description>
    <link>http://huyongde.github.io/2016/02/26/mysql-transaction-log.html</link>
    <guid>http://huyongde.github.io/2016/02/26/mysql-transaction-log</guid>
    <pubDate>Fri, 26 Feb 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>mysql 主从复制</title>
    <description>&lt;p&gt;###简介&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;MySQL的Replication是一个异步复制的过程,现在新的版本支持异步和半同步的过程，
它是从一个Mysql master 实例 复制到Mysql slave instance的过程。
在master与slave之间实现整个复制过程主要由三个线程来完成，
slave端包括SQL线程和IO线程，master端包括一个IO线程。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;要实现MySQL的Replication，第一必须打开master端的binlog。 因为mysql的整个主从复制过程实际上就是：
slave端从master端获取binlog日志，然后再在自己身上完全顺序的执行该日志中所记录的各种SQL操作。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###mysql 主从复制的具体过程&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;slave端的IO线程连接上master端，并请求从指定binlog日志文件的指定pos节点位置(或者从最开始的日志)开始复制之后的日志内容。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;master端在接收到来自slave端的IO线程请求后，通知master端负责复制binlog的IO线程，根据slave端IO线程的请求信息，读取指定binlog日志指定pos节点位置之后的日志信息，然后返回给slave端的IO线程。该返回信息中除了binlog日志所包含的信息之外，还包括本次返回的信息在master端的binlog文件名以及在该binlog日志中的pos节点位置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;slave端的IO线程在接收到master端IO返回的信息后，将接收到的binlog日志内容依次写入到slave端的relaylog文件(mysql-relay-bin.xxxxxx)的最末端，并将读取到的master端的binlog文件名和pos节点位置记录到master-info（该文件存在slave端）文件中，以便在下一次读取的时候能够清楚的告诉master“我需要从哪个binlog文件的哪个pos节点位置开始，请把此节点以后的日志内容发给我”。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;slave端的SQL线程在检测到relaylog文件中新增内容后，会马上解析该log文件中的内容。然后还原成在master端真实执行的那些SQL语句，并在自身按顺丰依次执行这些SQL语句。这样，实际上就是在master端和slave端执行了同样的SQL语句，所以master端和slave端的数据是完全一样的。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;#####复制过程简化描述如下：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;master在执行sql之后，记录二进制log文件（bin-log）。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;slave连接master，并从master获取binlog，存于本地relay-log中，然后从上次记住的位置起执行SQL语句，一旦遇到错误则停止同步。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

</description>
    <link>http://huyongde.github.io/2016/02/26/mysql-replication.html</link>
    <guid>http://huyongde.github.io/2016/02/26/mysql-replication</guid>
    <pubDate>Fri, 26 Feb 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>netstat 实际使用例子</title>
    <description>&lt;p&gt;&lt;strong&gt;本文参考:&lt;/strong&gt; &lt;a href=&quot;http://www.binarytides.com/linux-netstat-command-examples/&quot;&gt;&lt;strong&gt;netstat command examples&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;###netstat 简介&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;netstat - Print network connections, routing tables, interface statistics, 
masquerade connections, and multicast memberships
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;###netstat 使用例子&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;netstat -a  显示所有的网络连接&lt;/li&gt;
  &lt;li&gt;netstat -at; netstat -au  显示特定协议的连接， t 选项显示tcp协议， u 选项显示udp协议&lt;/li&gt;
  &lt;li&gt;netstat -atn  选项n显示ip,可以更快速的显示网络连接，不需要去把ip解析成域名&lt;/li&gt;
  &lt;li&gt;netstat -tln 选项l表示只显示监听状态的连接&lt;/li&gt;
  &lt;li&gt;netstat -nltp 选项p 显示连接对应的进程名字&lt;/li&gt;
  &lt;li&gt;netstat -nlte 选项e 显示连接的所有者&lt;/li&gt;
  &lt;li&gt;netstat -s 显示相关统计信息&lt;/li&gt;
  &lt;li&gt;netstat -r 显示内核路由信息&lt;/li&gt;
  &lt;li&gt;netstat -re 选项e 更友好的方式显示内核路由信息&lt;/li&gt;
  &lt;li&gt;netstat -tc 选项c 可以持续显示连接信息&lt;/li&gt;
  &lt;li&gt;netstat -g 显示多播相关信息&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###netstat返回结果解释&lt;/p&gt;

&lt;p&gt;` Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)`&lt;/p&gt;

&lt;p&gt;一般的返回结果都有如上几列&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ptoto 表示socket使用的协议&lt;/li&gt;
  &lt;li&gt;Recv-Q 数据已经在本地接收缓冲,但是还没有recv().&lt;/li&gt;
  &lt;li&gt;Send-Q 对方没有收到的数据或者说没有Ack的,还是本地缓冲区.&lt;/li&gt;
  &lt;li&gt;Local Address 本地地址&lt;/li&gt;
  &lt;li&gt;Foreign Address 远端地址&lt;/li&gt;
  &lt;li&gt;state socket链接的当前状态&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2016/01/17/shell-netstat-command.html</link>
    <guid>http://huyongde.github.io/2016/01/17/shell-netstat-command</guid>
    <pubDate>Sun, 17 Jan 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>抓包神器 charles, 抓移动端的包</title>
    <description>&lt;h3 id=&quot;简介&quot;&gt;简介&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;之前在thinkpad上，是用猎豹建wifi, 电脑建个热点，手机链接热点，然后wireshark抓包，
但是wireshark follow tcp 流之后看不到请求的response header,
 好坑，好坑，好坑(很low的，大家轻拍)

自从转战mac之后，就没再怎么定位移动端的问题了， 最近PM们又开始说移动端有问题了，
然后说是我们server导致的, 又有了抓移动端的包的需求.

从全能QA 同学那里了解到了charles,看了第一眼我就爱上了这个东西，
logo既然是个大茶壶,谁都不要阻拦我去用它。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;charles官网&lt;a href=&quot;http://www.charlesproxy.com/&quot;&gt;charles&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;安装&quot;&gt;安装&lt;/h3&gt;
&lt;p&gt;charles需要是付费的，自然需要安装破解版，&lt;/p&gt;

&lt;p&gt;安装文件和破解jar见网盘链接  &lt;a href=&quot;http://pan.baidu.com/s/1i4s3rlr&quot;&gt;链接&lt;/a&gt; 密码: wg2v&lt;/p&gt;

&lt;p&gt;安装很简单，下面说下如何破解， 下载分享链接中的charles.jar,放到指定charles安装的指定目录中，替换原来的charles.jar,如何替换请看下面两个图片：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/charles.png&quot; alt=&quot;one&quot; /&gt;
&lt;img src=&quot;/image/charles2.png&quot; alt=&quot;two&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;使用1&quot;&gt;使用1&lt;/h3&gt;

&lt;p&gt;启动charles之后，本机端口8888会被监听，若想抓移动端的包，&lt;/p&gt;

&lt;p&gt;需要手动设置移动端的网络代理,设置成本机的ip, port 是8888， 本机ip获取可以通过 (系统偏好设置-&amp;gt;网络皆可以看得到)，&lt;/p&gt;

&lt;p&gt;我的手机是屌丝小米手机，设置截图如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/charles3.png&quot; alt=&quot;mi note set&quot; /&gt;&lt;/p&gt;

&lt;p&gt;设置好了之后就可以看到移动端访问网络的包了。&lt;/p&gt;

&lt;h3 id=&quot;使用2&quot;&gt;使用2&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;抓取移动端的https包
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;移动端需要配置： 对于移动端https的包，需要移动端额外安装个证书才行，移动端浏览器下载 网盘链接  &lt;a href=&quot;http://pan.baidu.com/s/1i4s3rlr&quot;&gt;链接&lt;/a&gt; 密码: wg2v&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charles-proxy-ssl-proxying-certificate.crt&lt;/code&gt; 文件提示要安装，随便给证书起个名字，安装好， 移动端配置完成。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;charles需要的配置： charles菜单栏的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proxy&lt;/code&gt; =&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proxy setting&lt;/code&gt; =&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSL&lt;/code&gt; =&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enable SSL Proxying&lt;/code&gt; ; 之后配置Locations: host为*， port 为443.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;配置好移动端和charles之后就可以看到详细的https的信息了。

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;抓取本机的包&quot;&gt;抓取本机的包&lt;/h3&gt;

&lt;p&gt;我这遇到一个问题，安装了之后，mac本机的包既然抓不到， 同理，我也去&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;系统偏好设置-&amp;gt;网络&lt;/code&gt;面板，选定mac当前链接的网络，点击&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;高级&lt;/code&gt;
出现如下面板，在代理中设置web代理为本机8888端口， 就可以从charles看到mac本机的包了。 代理配置如下图：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/charles4.png&quot; alt=&quot;mac本机设置&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;以后再也不怕抓不到移动端的包了。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;charles是java开发的，可移植性很好，支持各个系统，只要有java环境就好。&lt;/strong&gt;&lt;/p&gt;

&lt;h4 id=&quot;参考&quot;&gt;参考&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.csdn.net/jiangwei0910410003/article/details/41620363&quot;&gt;mac上抓包工具Charles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    <link>http://huyongde.github.io/2016/01/15/charles-packet-sniffer.html</link>
    <guid>http://huyongde.github.io/2016/01/15/charles-packet-sniffer</guid>
    <pubDate>Fri, 15 Jan 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>go import 导入包介绍</title>
    <description>&lt;h2 id=&quot;0-简介&quot;&gt;0. 简介&lt;/h2&gt;
&lt;p&gt;import 在go编程中用来导入go语言标准库，或者开发者自己写的go库，本文主要介绍下import导入包的各种方式&lt;/p&gt;

&lt;h2 id=&quot;1-import-引入go库的方法&quot;&gt;1. import 引入go库的方法&lt;/h2&gt;

&lt;h3 id=&quot;11-导入go语言标准库&quot;&gt;1.1 导入go语言标准库&lt;/h3&gt;

&lt;p&gt;eg:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import &quot;fmt&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;import导入go语言标准库， 实际上是引入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$GOROOT/src&lt;/code&gt;下面导入对应文件夹下的go文件&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;12-相对路径导入go库&quot;&gt;1.2 相对路径导入go库&lt;/h3&gt;
&lt;p&gt;eg:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import &quot;./model&quot; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;引入当前同一目录下的model&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;13-绝对路径导入go库&quot;&gt;1.3 绝对路径导入go库&lt;/h3&gt;

&lt;p&gt;eg:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import 'log/mylog' 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;导入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$GOPATH/src/log/mylog&lt;/code&gt;目录下的go文件&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;14-import-的几种特殊方式&quot;&gt;1.4 import 的几种特殊方式&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;点操作 有时候会看到如下的方式导入包&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import . &quot;fmt&quot;&lt;/code&gt; 这个点操作的含义就是这个包导入之后在你调用这个包的函数时，你可以省略前缀包名，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fmt.Println(&quot;hello world &quot;)&lt;/code&gt; 可以简写成&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Println(&quot;hello world&quot;)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;别名操作 别名操作顾名思义可以把包命名成另一个用起来容易记忆的名字 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import( f &quot;fmt&quot;)&lt;/code&gt; 调用包函数的时候可以用重命名的简洁的前缀，eg: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f.Println(&quot;hello world&quot;)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;_操作 _操作其实只是引入该包。当导入一个包时，它所有的init()函数就会被执行，但有些时候并非真的需要使用这些包，仅仅是希望它的init()函数被执行而已。这个时候就可以使用_操作引用该包了。即使用_操作引用包是无法通过包名来调用包中的导出函数，而是只是为了简单的调用其init函数()。&lt;/li&gt;
&lt;/ul&gt;

</description>
    <link>http://huyongde.github.io/2016/01/12/go-import.html</link>
    <guid>http://huyongde.github.io/2016/01/12/go-import</guid>
    <pubDate>Tue, 12 Jan 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>select poll epoll 简单介绍和比较</title>
    <description>&lt;p&gt;###0. 简介&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;select，poll，epoll都是IO多路复用的机制。I/O多路复用就通过一种机制，实现单线程可以监视多个描述符，一旦某个描述符就绪（一般是读就绪或者写就绪），能够通知程序进行相应的读写操作。&lt;/li&gt;
  &lt;li&gt;但select，poll，epoll本质上都是同步I/O，因为他们都需要在读写事件就绪后自己负责进行读写，也就是说这个读写过程是阻塞的。&lt;/li&gt;
  &lt;li&gt;而异步I/O则无需自己负责进行读写，异步I/O的实现会负责把数据从内核拷贝到用户空间。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###1. select&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;select最早于1983年出现在4.2BSD中，它通过一个select()系统调用来监视多个文件描述符的数组，当select()返回后，该数组中就绪的文件描述符便会被内核修改标志位，使得进程可以获得这些文件描述符从而进行后续的读写操作。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;select目前几乎在所有的平台上支持，其良好跨平台支持也是它的一个优点，事实上从现在看来，这也是它所剩不多的优点之一。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制，在Linux上一般为1024，不过可以通过修改宏定义甚至重新编译内核的方式提升这一限制。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;另外，select()所维护的存储大量文件描述符的数据结构，随着文件描述符数量的增大，其复制的开销也线性增长。同时，由于网络响应时间的延迟使得大量TCP连接处于非活跃状态，但调用select()会对所有socket进行一次线性扫描，所以这也浪费了一定的开销。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###2. poll&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;poll在1986年诞生于System V Release 3，它和select在本质上没有多大差别，但是poll没有最大文件描述符数量的限制。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;poll和select同样存在一个缺点就是，包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间，而不论这些文件描述符是否就绪，它的开销随着文件描述符数量的增加而线性增大。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;另外，select()和poll()将就绪的文件描述符告诉进程后，如果进程没有对其进行IO操作，那么下次调用select()和poll()的时候将再次报告这些文件描述符，所以它们一般不会丢失就绪的消息，这种方式称为水平触发（Level Triggered）。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###3.epoll 
直到Linux2.6才出现了由内核直接支持的实现方法，那就是epoll，它几乎具备了之前所说的一切优点，被公认为Linux2.6下性能最好的多路I/O就绪通知方法。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;epoll可以同时支持水平触发和边缘触发（Edge Triggered，只告诉进程哪些文件描述符刚刚变为就绪状态，它只说一遍，如果我们没有采取行动，那么它将不会再次告知，这种方式称为边缘触发），理论上边缘触发的性能要更高一些，但是代码实现相当复杂。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;epoll同样只告知那些就绪的文件描述符，而且当我们调用epoll_wait()获得就绪文件描述符时，返回的不是实际的描述符，而是一个代表就绪描述符数量的值，你只需要去epoll指定的一个数组中依次取得相应数量的文件描述符即可，这里也使用了内存映射（mmap）技术，这样便彻底省掉了这些文件描述符在系统调用时复制的开销。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;另一个本质的改进在于epoll采用基于事件的就绪通知方式。在select/poll中，进程只有在调用一定的方法后，内核才对所有监视的文件描述符进行扫描，而epoll事先通过epoll_ctl()来注册一个文件描述符，一旦基于某个文件描述符就绪时，内核会采用类似callback的回调机制，迅速激活这个文件描述符，当进程调用epoll_wait()时便得到通知。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2016/01/11/select-poll-epoll.html</link>
    <guid>http://huyongde.github.io/2016/01/11/select-poll-epoll</guid>
    <pubDate>Mon, 11 Jan 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>icmp ping flood attack( one of DOS attack</title>
    <description>&lt;p&gt;###参考
&lt;a href=&quot;http://www.binarytides.com/icmp-ping-flood-code-sockets-c-linux/&quot;&gt;icmp ping flood&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DOS :&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2016/01/09/icmp-ping-flood.html</link>
    <guid>http://huyongde.github.io/2016/01/09/icmp-ping-flood</guid>
    <pubDate>Sat, 09 Jan 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>vim go 开发环境配置</title>
    <description>&lt;h2 id=&quot;参考&quot;&gt;参考&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/01.4.md&quot;&gt;goweb 编程-go开发工具&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.kissdata.com/2014/06/18/vim-golang.html&quot;&gt;配置vim go 开发环境&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;简介&quot;&gt;简介&lt;/h2&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;搭建vim 开发golang的环境,作为一个初级vimer，慢慢向高级迈进。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;0vim插件管理工具-vundle&quot;&gt;0.vim插件管理工具 vundle&lt;/h4&gt;
&lt;p&gt;vundle 安装和使用，参考&lt;a href=&quot;http://huyongde.github.io/2016/01/02/vim-plugin-bundler-vundle.html&quot;&gt;vundle 管理vim插件&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&quot;01-go相关tools安装&quot;&gt;0.1 go相关tools安装&lt;/h4&gt;

&lt;p&gt;通过vim中&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:GoInstallBinaries&lt;/code&gt; 来安装go开发相关的tools, （GoInstallBinaries 依赖mercurial需要先命令行安装mercurial, mercurial是google开发的类似于svn，git的代码托管服务）
安装完成后，tools的bin文件在$GOPATH/bin下.
我安装完后$GOPATH/bin下二进制文件如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rwxr-xr-x  1 huyongde  staff   3.6M  1  8 10:27 gotags
-rwxr-xr-x  1 huyongde  staff   5.8M  1  8 10:27 errcheck
-rwxr-xr-x  1 huyongde  staff   6.0M  1  8 10:27 golint
-rwxr-xr-x  1 huyongde  staff   6.3M  1  8 10:27 gorename
-rwxr-xr-x  1 huyongde  staff   9.1M  1  8 10:27 oracle
-rwxr-xr-x  1 huyongde  staff   6.0M  1  8 10:19 godef
-rwxr-xr-x  1 huyongde  staff   6.2M  1  8 10:19 gometalinter
-rwxr-xr-x  1 huyongde  staff    10M  1  8 10:18 gocode
-rwxr-xr-x  1 huyongde  staff   5.0M  1  8 02:48 goimports
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;1vim-go-插件&quot;&gt;1.vim go 插件&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/dgryski/vim-godef&quot;&gt;vim-godef github 详细介绍&lt;/a&gt;  此插件依赖GoInstallBinaries安装的godef, vimrc需要加的配置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bundle 'dgryski/vim-godef'&lt;/code&gt; ,之后可以打开go文件，把光标移动到指定函数就可以使用vim normal模式下的gd命令查看对应函数的定义了。
godef显示方式配置，在vimrc中加入:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;&quot;&quot;set for godef
let g:godef_split=3 &quot;&quot;&quot;打开新窗口的时候左右split
let g:godef_same_file_in_same_window=1 &quot;&quot;&quot;函数在同一个文件中时不需要打开新窗口
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/nsf/gocode&quot;&gt;vim-gocode github 详细介绍&lt;/a&gt; 此插件依赖GoInstallBinaries安装的gocode, vimrc需要配置&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Plugin 'nsf/gocode', {'rtp': 'vim/'}&lt;/code&gt;, 做go代码的补全。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/Valloric/YouCompleteMe&quot;&gt;YouCompleteMe github 详细介绍&lt;/a&gt; 配合gocode，做代码补全，简直棒棒的, 需要vimrc配置&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt; Plugin 'Valloric/YouCompleteMe'&lt;/code&gt; .&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/majutsushi/tagbar&quot;&gt;tagbar  github 详细介绍&lt;/a&gt; 此插件和taglist类似，用来显示go中相关func method variable 等的定义， 此插件需要依赖GoInstallBinaries安装的gotags, vimrc需要配置&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Bundle 'majutsushi/tagbar'

&quot;&quot;&quot;&quot;set for tagbar start
let g:tagbar_type_go = {
    \ 'ctagstype' : 'go',
    \ 'kinds'     : [
        \ 'p:package',
        \ 'i:imports:1',
        \ 'c:constants',
        \ 'v:variables',
        \ 't:types',
        \ 'n:interfaces',
        \ 'w:fields',
        \ 'e:embedded',
        \ 'm:methods',
        \ 'r:constructor',
        \ 'f:functions'
    \ ],
    \ 'sro' : '.',
    \ 'kind2scope' : {
        \ 't' : 'ctype',
        \ 'n' : 'ntype'
    \ },
    \ 'scope2kind' : {
        \ 'ctype' : 't',
        \ 'ntype' : 'n'
    \ },
    \ 'ctagsbin'  : 'gotags',
    \ 'ctagsargs' : '-sort -silent'
    \ }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;目前我的vim为go的配置如下&quot;&gt;目前我的vim为go的配置如下:&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;&quot;&quot;&quot;&quot;&quot;set for go start
     Plugin 'fatih/vim-go'
     Bundle 'elgris/hint'
     Plugin 'Valloric/YouCompleteMe'
     Plugin 'majutsushi/tagbar'
     Bundle 'scrooloose/nerdtree'
     Bundle 'dgryski/vim-godef'
     Plugin 'nsf/gocode', {'rtp': 'vim/'}

&quot;&quot;&quot;&quot;set for godef
let g:godef_split=3 &quot;&quot;&quot;打开新窗口的时候左右split
let g:godef_same_file_in_same_window=1 &quot;&quot;&quot;函数在同一个文件中时不需要打开新窗口

&quot;&quot;&quot;&quot;set for tagbar start
let g:tagbar_type_go = {
    \ 'ctagstype' : 'go',
    \ 'kinds'     : [
        \ 'p:package',
        \ 'i:imports:1',
        \ 'c:constants',
        \ 'v:variables',
        \ 't:types',
        \ 'n:interfaces',
        \ 'w:fields',
        \ 'e:embedded',
        \ 'm:methods',
        \ 'r:constructor',
        \ 'f:functions'
    \ ],
    \ 'sro' : '.',
    \ 'kind2scope' : {
        \ 't' : 'ctype',
        \ 'n' : 'ntype'
    \ },
    \ 'scope2kind' : {
        \ 'ctype' : 't',
        \ 'ntype' : 'n'
    \ },
    \ 'ctagsbin'  : 'gotags',
    \ 'ctagsargs' : '-sort -silent'
    \ }
&quot;&quot;&quot;set for tagbar end 

&quot;&quot;&quot;set for goimports
&quot;&quot;&quot;end goimports

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;godef遇到的问题&quot;&gt;godef遇到的问题&lt;/h3&gt;

&lt;h5 id=&quot;问题内容&quot;&gt;问题内容：&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Error detected while processing function GodefUnderCursor[10]..Godef:
line   21:
E926: Current location list was changed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;解决方法&quot;&gt;解决方法：&lt;/h5&gt;

&lt;blockquote&gt;
  &lt;p&gt;升级syntastic 到最新代码， 设置，let g:syntastic_check_on_open = 0 为0 可以解决vim中golang代码跳转的问题&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;暂时这么多，后续再补充&lt;/strong&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2016/01/08/go-vim-development-plugin.html</link>
    <guid>http://huyongde.github.io/2016/01/08/go-vim-development-plugin</guid>
    <pubDate>Fri, 08 Jan 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>jekyll 相关资料汇总</title>
    <description>&lt;p&gt;##参考&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://jekyllrb.com/&quot;&gt;&lt;strong&gt;jekyll 官网&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://jekyllrb.com/docs/home/&quot;&gt;&lt;strong&gt;jekyll document&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Shopify/liquid/wiki/Liquid-for-Designers&quot;&gt;&lt;strong&gt;liquid语法介绍&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;下定决心要好好学习下jekyll, 之后好完善自己的blog&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;###需要学习的资料&lt;/p&gt;

&lt;p&gt;####jekyll相关&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://jekyllrb.com/docs/variables/&quot;&gt;jekyll variables&lt;/a&gt;  jekyll 相关的变量， 从总可以学习如何获得整个站点或者一个page的各项信息。&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://jekyllrb.com/docs/configuration/&quot;&gt;jekyll _config.yml详细介绍&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;liquid-模块相关&quot;&gt;liquid 模块相关&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Shopify/liquid/wiki/Liquid-for-Designers&quot;&gt;liquid 语法介绍&lt;/a&gt; 介绍稀奇古怪的liquid 模块的语法&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;####frontmatter 相关&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://jekyllrb.com/docs/frontmatter/&quot;&gt;yaml frontmatter&lt;/a&gt; 介绍了如何写每个page的头信息,比如layout, tags, title 等。&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://jekyllrb.com/docs/configuration/#front-matter-defaults&quot;&gt;frontmatter 各变量默认值设置&lt;/a&gt; 介绍如何设置frontmatter 各变量的默认值。&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2016/01/05/jekyll-deep-learn.html</link>
    <guid>http://huyongde.github.io/2016/01/05/jekyll-deep-learn</guid>
    <pubDate>Tue, 05 Jan 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>为blog添加归档页 archives</title>
    <description>&lt;p&gt;##参考
&lt;a href=&quot;http://mikerowecode.com/2010/08/jekyll_archives_grouped_by_year.html&quot;&gt;&lt;strong&gt;Jekyll archives grouped by date&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;blog 根目录下创建文件， archives.html , 内容如下：&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;---
layout: page
permalink: /archives/
---

&lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Archives&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  {% for post in site.posts %}

    {% unless post.next %}
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;{{ post.date | date: '%Y' }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
    {% else %}
      {% capture year %}{{ post.date | date: '%Y' }}{% endcapture %}
      {% capture nyear %}{{ post.next.date | date: '%Y' }}{% endcapture %}
      {% if year != nyear %}
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;{{ post.date | date: '%Y' }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
      {% endif %}
    {% endunless %}

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;{{ post.date | date:&quot;%b&quot; }} &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ post.url }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  {% endfor %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;之后就可以通过huyongde.github.io/archives来访问 按照年份归档的页面了&lt;/strong&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2016/01/05/jekyll-archive.html</link>
    <guid>http://huyongde.github.io/2016/01/05/jekyll-archive</guid>
    <pubDate>Tue, 05 Jan 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>显示post的相关文章(有相同的tag) related_posts</title>
    <description>&lt;p&gt;##参考&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://zhangwenli.com/blog/2014/07/15/jekyll-related-posts-without-plugin/&quot;&gt;jekyll related_posts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##不用插件,显示文章相类似文章&lt;/p&gt;

&lt;p&gt;直接把显示相似文章的代码放到了_layout/post.html中了，为每个post显示相关的posts。&lt;/p&gt;

&lt;p&gt;代码如下&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;float:right;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    {% assign hasSimilar = '' %}
    {% for post in site.related_posts %}
        {% assign postHasSimilar = false %}
        {% for tag in post.tags %}
            {% if postHasSimilar == false %}
                {% for thisTag in page.tags %}
                    {% if postHasSimilar == false and hasSimilar.size &lt;span class=&quot;nt&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;tag =&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;thisTag&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;%}&lt;/span&gt;
                        &lt;span class=&quot;err&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hasSimilar.size =&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;%}&lt;/span&gt;
                            &lt;span class=&quot;err&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;h3&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;page-heading&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;相关文章:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
                            &lt;span class=&quot;nt&quot;&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
                        {% endif %}
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post-meta&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.date | date: &quot;%b %-d, %Y&quot; }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;

                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;h5&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ post.url | prepend: site.baseurl }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;/h5&amp;gt;&lt;/span&gt;
                        {% assign postHasSimilar = true %}
                    {% endif %}
                {% endfor %}
            {% endif %}
        {% endfor %}

        {% if postHasSimilar == true %}
            {% capture hasSimilar %}{{ hasSimilar }}*{% endcapture %}
        {% endif %}
    {% endfor %}

    {% if hasSimilar.size &amp;gt; 0 %}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
    {% endif %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;我的blog就是左边显示相关的posts，右边显示最新更新的文章。&lt;/p&gt;

&lt;p&gt;####自己主要修改的地方：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;支持正确的显示5个相关文章, 使用的是site.posts，而不是site.related_posts.
 related_posts是一个不包括当前post的，本站的最新的10个post,再久远的就不包括在related_post中了, &lt;a href=&quot;http://jekyllrb.com/docs/variables/&quot;&gt;jekyll variables&lt;/a&gt; 中有介绍。&lt;/li&gt;
  &lt;li&gt;使用site.posts之后,通过post.id的比较来过滤当前post.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;效果见本博客。&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2016/01/04/related-posts.html</link>
    <guid>http://huyongde.github.io/2016/01/04/related-posts</guid>
    <pubDate>Mon, 04 Jan 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>jekyll-paginate 为blog添加分页功能</title>
    <description>&lt;p&gt;##参考&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://jekyllrb.com/docs/pagination/&quot;&gt;&lt;strong&gt;jekyll-paginate&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;按照教程一步步的来，最终可以搞定&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;有两种显示分页的方式，一个是不显示全部的分页&lt;/li&gt;
  &lt;li&gt;显示全部的分页的方式&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2016/01/04/jekyll-paginate.html</link>
    <guid>http://huyongde.github.io/2016/01/04/jekyll-paginate</guid>
    <pubDate>Mon, 04 Jan 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>为blog添加pv uv 计数</title>
    <description>&lt;p&gt;##参考
&lt;a href=&quot;http://ibruce.info/2015/04/04/busuanzi/&quot;&gt;&lt;strong&gt;不蒜子&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;##简介&lt;/p&gt;

&lt;p&gt;通过 不蒜子 提供的计数服务，很简单的为自己的网站添加计数功能。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;必须的安装脚本&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;js实现的，需要引入js脚本，代码如下:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;##2. pv uv 标签&lt;/p&gt;

&lt;p&gt;####2.1 PV 标签
单个用户点击n次，当做n次访问&lt;/p&gt;

&lt;p&gt;标签代码如下：&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;busuanzi_container_site_pv&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    本站总访问量&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;busuanzi_value_site_pv&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;次
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;####2.2 UV 标签
单个用户连续点击n次，只记录一次访客数&lt;/p&gt;

&lt;p&gt;UV 标签代码如下：&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;busuanzi_container_site_uv&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  本站访客数&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;busuanzi_value_site_uv&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;人次
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;####2.3 单页PV计数
标签代码如下:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;busuanzi_container_page_pv&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  本文总阅读量&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;busuanzi_value_page_pv&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;次
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;不蒜子 网站统计 很赞。亲测，很好用， 易用。&lt;/strong&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2016/01/04/blog-pv-uv.html</link>
    <guid>http://huyongde.github.io/2016/01/04/blog-pv-uv</guid>
    <pubDate>Mon, 04 Jan 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>为jekyll搭建的blog生成tags页面</title>
    <description>&lt;p&gt;##参考&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.meinside.pe.kr/Adding-tag-cloud-and-archives-page-to-Jekyll/&quot;&gt;Adding tag cloud and archives page to Jekyll&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;##简介
本文介绍如何不使用插件为github page添加标签页&lt;/p&gt;

&lt;p&gt;##1. touch tags.html&lt;/p&gt;

&lt;p&gt;在博客根目录生成一个tags.html文件，内容如下：&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;---
layout: page
permalink: /tags/
---
&lt;span class=&quot;nt&quot;&gt;&amp;lt;ul&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tag-cloud&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
{% for tag in site.tags %}
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;font-size: {{ tag | last | size | times: 100 | divided_by: site.tags.size | plus: 70  }}%&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#{{ tag | first | slugize }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      {{ tag | first }}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
{% endfor %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;archives&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
{% for tag in site.tags %}
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;archive-group&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    {% capture tag_name %}{{ tag | first }}{% endcapture %}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;h3&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#{{ tag_name | slugize }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{{ tag_name }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ tag_name | slugize }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    {% for post in site.tags[tag_name] %}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;article&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;archive-item&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;h4&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ root_url }}{{ post.url }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{{post.title}}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
    {% endfor %}
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
{% endfor %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;创建之后可以,可用通过root_url/tags来访问，比如我的就是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://huyongde.github.io/tags/&lt;/code&gt; 来访问tags页面&lt;/p&gt;

&lt;p&gt;##2. 为每个post文章添加相关的tag链接&lt;/p&gt;

&lt;p&gt;新建一个文件&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_include/post-tag.html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;内容如下:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post-tags&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  Tags: 
  {% if post %}
    {% assign tags = post.tags %}
  {% else %}
    {% assign tags = page.tags %}
  {% endif %}
  {% for tag in tags %}
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/tags/#{{tag|slugize}}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{{tag}}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;{% unless forloop.last %},{% endunless %}
  {% endfor %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;在_layout/post.html中想要添加相关tag链接的地方加入代码&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;{% include post-tags.html %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;我的_layout/post.html修改的内容如下:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;       &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post-title&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemprop=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name headline&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.title }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
       {% include post-tag.html %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;##3. 添加css配置&lt;/p&gt;

&lt;p&gt;需要添加的内容如下:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;tag&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;cloud&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;archives&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.tag-cloud&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;list-style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;justify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
  &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;16px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inline-block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;12px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;12px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;#archives&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.archive-group&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;border-top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;solid&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#ddd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.archive-item&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.post-tags&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;##4. 效果&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;tags页效果: &lt;img src=&quot;/image/tags.png&quot; alt=&quot;tags&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;post页效果: &lt;img src=&quot;/image/post.png&quot; alt=&quot;post&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

</description>
    <link>http://huyongde.github.io/2016/01/03/jekyll-tags-page.html</link>
    <guid>http://huyongde.github.io/2016/01/03/jekyll-tags-page</guid>
    <pubDate>Sun, 03 Jan 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>vim 插件管理 vundle</title>
    <description>&lt;p&gt;##参考
&lt;a href=&quot;http://jasonding1354.github.io/2015/04/29/Developer%20Kits/%E3%80%90Vim%E3%80%91%E4%BD%BF%E7%94%A8Vundle%E7%AE%A1%E7%90%86%E9%85%8D%E7%BD%AEVim%E5%9F%BA%E6%9C%AC%E6%8F%92%E4%BB%B6/&quot;&gt;&lt;strong&gt;&lt;em&gt;vundle配置vim使用的基本插件needtree, taglist等&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
##1. 简介&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim 是程序员最受欢迎的coding神器，没有之一。 合理使用插件可以做到事半功倍的效果。  vundle 把git整合到插件管理中，用户需要做的只是去Github上找到自己想要的插件的名字，安装，更新和卸载都可有vundle来完成了。 虽然去发现一个好的插件仍然是一个上下求索的过程，但是用户已经可以从安装配置的繁琐过程解脱了。 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/VundleVim/Vundle.vim&quot;&gt;Vundle git repo&lt;/a&gt; 介绍了如何安装vundle和通过vundle来安装vim插件&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/VundleVim/Vundle.vim/blob/master/doc/vundle.txt&quot;&gt;vundle.txt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##2. 安装&amp;amp;&amp;amp;使用&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;下载vundle：&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;下载完成之后，在vimrc中添加配置：&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;set nocompatible               &quot; be iMproved
 filetype off                   &quot; required!

 set rtp+=~/.vim/bundle/vundle/
 call vundle#rc()

 &quot; let Vundle manage Vundle
 &quot; required! 
 Bundle 'gmarik/vundle'

 &quot; My Bundles here:
 #以后你想安装什么插件可以写在下面
 &quot;
 &quot; original repos on github 
#如果你的插件来自github，写在下方，只要作者名/项目名就行了
 Bundle 'tpope/vim-fugitive' #如这里就安装了vim-fugitive这个插件
 Bundle 'Lokaltog/vim-easymotion'
 Bundle 'rstacruz/sparkup', {'rtp': 'vim/'}
 Bundle 'tpope/vim-rails.git'
 &quot; vim-scripts repos
#如果插件来自 vim-scripts，你直接写插件名就行了
 Bundle 'L9'
 Bundle 'FuzzyFinder'
 &quot; non github repos
#如使用自己的git库的插件，像下面这样做
 Bundle 'git://git.wincent.com/command-t.git'
 &quot; git repos on your local machine (ie. when working on your own plugin)
 Bundle 'file:///Users/gmarik/path/to/plugin'
 &quot; ...

 filetype plugin indent on     &quot; required!
#下面是 vundle的一些命令代会会用到
 &quot;
 &quot; Brief help
 &quot; :BundleList          - list configured bundles
 &quot; :BundleInstall(!)    - install(update) bundles
 &quot; :BundleSearch(!) foo - search(or refresh cache first) for foo
 &quot; :BundleClean(!)      - confirm(or auto-approve) removal of unused bundles
 &quot;
 &quot; see :h vundle for more details or wiki for FAQ
 &quot; NOTE: comments after Bundle command are not allowed..
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;vim 任意打开文件， 运行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:PluginInstall&lt;/code&gt; 就会安装vimrc中Plugin配置的需要安装的插件
    &lt;ul&gt;
      &lt;li&gt;Plugin ‘VundleVim/Vundle.vim’ 配置vundle&lt;/li&gt;
      &lt;li&gt;另外配置了其他一些vim 插件， 如L9等。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

</description>
    <link>http://huyongde.github.io/2016/01/02/vim-plugin-bundler-vundle.html</link>
    <guid>http://huyongde.github.io/2016/01/02/vim-plugin-bundler-vundle</guid>
    <pubDate>Sat, 02 Jan 2016 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>go 基础学习</title>
    <description>&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;本文将介绍如何定义变量、常量、Go语言内置类型及Go语言程序设计中的一些技巧。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;定义变量&quot;&gt;定义变量&lt;/h2&gt;
&lt;p&gt;Go语言里面定义变量有多种方式。&lt;/p&gt;

&lt;p&gt;使用var关键字是Go语言最基本的定义变量方式，与C语言不同的是Go语言把变量类型放在变量名后面，如下所示。&lt;/p&gt;

&lt;h4 id=&quot;定义一个变量&quot;&gt;定义一个变量&lt;/h4&gt;

&lt;p&gt;//定义一个名称为“variableName”，类型为”type”的变量&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var variableName type
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;定义多个变量&quot;&gt;定义多个变量。&lt;/h4&gt;

&lt;p&gt;//定义三个类型都是“type”的三个变量&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var vname1, vname2,vname3 type
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;定义变量并初始化值&quot;&gt;定义变量并初始化值。&lt;/h4&gt;

&lt;p&gt;//初始化“variableName”的变量为“value”值，类型是“type”&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var variableName type= value
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;同时初始化多个变量&quot;&gt;同时初始化多个变量。&lt;/h4&gt;

&lt;p&gt;定义三个类型都是”type”的三个变量,并且它们分别初始化相应的值
vname1为v1，vname2为v2，vname3为v3&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var vname1, vname2, vname3 type= v1, v2, v3

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;
&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;你是不是觉得上面这样的定义有点繁琐？没关系，因为Go语言的设计者也发现了，有一种写法可以让它变得简单一点。我们可以直接忽略类型声明，那么上面的代码变成如下所示。&lt;/em&gt;&lt;/p&gt;

&lt;h4 id=&quot;定义三个变量它们分别初始化相应的值&quot;&gt;定义三个变量，它们分别初始化相应的值&lt;/h4&gt;

&lt;p&gt;vname1为v1，vname2为v2，vname3为v3&lt;/p&gt;

&lt;p&gt;然后Go会根据其相应值的类型来帮你初始化它们&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var vname1, vname2, vname3 = v1, v2, v3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;你觉得上面的还是有些繁琐好吧让我们继续简化&quot;&gt;你觉得上面的还是有些繁琐？好吧，让我们继续简化。&lt;/h4&gt;

&lt;p&gt;定义三个变量，它们分别初始化相应的值&lt;/p&gt;

&lt;p&gt;vname1为v1，vname2为v2，vname3为v3&lt;/p&gt;

&lt;p&gt;编译器会根据初始化的值自动推导出相应的类型&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vname1, vname2, vname3 := v1, v2, v3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;现在是不是看上去非常简洁了&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:=&lt;/code&gt; 这个符号直接取代了var和type，这种形式叫做简短声明。&lt;/p&gt;

&lt;p&gt;不过它有一个限制，&lt;strong&gt;&lt;em&gt;那就是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:=&lt;/code&gt;只能用在函数内部；在函数外部使用则会无法编译通过，所以一般用var方式来定义全局变量。&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h5 id=&quot;_下画线是个特殊的变量名任何赋予它的值都会被丢弃在这个例子中我们将值35赋予b并同时丢弃34&quot;&gt;_（下画线）是个特殊的变量名，任何赋予它的值都会被丢弃。在这个例子中，我们将值35赋予b，并同时丢弃34。&lt;/h5&gt;

&lt;p&gt;_, b := 34, 35
Go语言对于已声明但未使用的变量会在编译阶段报错，比如下面的代码就会产生一个错误：声明了i但未使用。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package main

func main() {
    var i int
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;常量&quot;&gt;常量&lt;/h2&gt;

&lt;p&gt;所谓常量，也就是在程序编译阶段就确定下来的值，而程序在运行时则无法改变该值。在Go语言程序中，常量可定义为数值、布尔值或字符串等类型。&lt;/p&gt;

&lt;p&gt;它的语法如下。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;const constantName =value

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;//如果需要，也可以明确指定常量的类型：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;const Pi float32 =3.1415926
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;以下是一些常量声明的例子&quot;&gt;以下是一些常量声明的例子。&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;const Pi = 3.1415926
const i = 10000
const MaxThread = 10
const prefix =&quot;astaxie_&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;内置基础类型&quot;&gt;内置基础类型&lt;/h2&gt;
&lt;h3 id=&quot;boolean&quot;&gt;Boolean&lt;/h3&gt;
&lt;p&gt;在Go语言中，布尔值的类型为bool，值是true或false，&lt;strong&gt;默认为false&lt;/strong&gt;。&lt;/p&gt;

&lt;h5 id=&quot;示例代码&quot;&gt;示例代码&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var isActivebool  // 全局变量声明
var enabled, disabled= true, false  // 忽略类型的声明

func test() {
    var available bool  // 一般声明
    valid := false      // 简短声明
    available = true    // 赋值操作
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;数值类型&quot;&gt;数值类型&lt;/h2&gt;

&lt;p&gt;整数类型有无符号和带符号两种。Go语言同时支持int和uint，这两种类型的长度相同，但具体长度取决于不同编译器的实现。&lt;/p&gt;

&lt;p&gt;当前的gcc和gccgo编译器在32位和64位平台上都使用32位来表示int和uint，但未来在64位平台上可能增加到64位。&lt;/p&gt;

&lt;p&gt;Go语言里面也有直接定义好位数的类型：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rune，int8，int16，int32，int64和byte，uint8，uint16，uint32，uint64&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;这就是全部吗？不止，Go语言还支持复数。它的默认类型是complex128（64位实数+64位虚数）。&lt;/p&gt;

&lt;p&gt;如果需要小一些的，也有complex64（32位实数+32位虚数）。复数的形式为RE + IMi，其中RE是实数部分，IM是虚数部分，而最后的i是虚数单位。&lt;/p&gt;

&lt;p&gt;下面是一个使用复数的例子。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var c complex64 = 5+5i
//output: (5+5i)
fmt.Printf(&quot;Value is: %v&quot;, c)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;字符串&quot;&gt;字符串&lt;/h2&gt;

&lt;p&gt;Go语言中的字符串都是采用UTF-8字符集编码。&lt;/p&gt;

&lt;p&gt;字符串是用一对&lt;strong&gt;&lt;em&gt;双引号&lt;/em&gt;&lt;/strong&gt;（”“）或&lt;strong&gt;&lt;em&gt;反引号&lt;/em&gt;&lt;/strong&gt;（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt; &lt;/code&gt;）括起来定义，它的类型是string。&lt;/p&gt;

&lt;p&gt;//示例代码&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var frenchHello string  // 声明变量为字符串的一般方法
var emptyString string = &quot;&quot; // 声明了一个字符串变量，初始化为空字符串
func test() {
    no, yes, maybe :=&quot;no&quot;, &quot;yes&quot;, &quot;maybe&quot;  // 简短声明，同时声明多个变量
    japaneseHello :=&quot;Ohaiou&quot;  // 同上
    frenchHello =&quot;Bonjour&quot;  // 常规赋值
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;在go语言中字符串是不可变的例如以下代码编译时会报错&quot;&gt;在Go语言中字符串是不可变的，例如，以下代码编译时会报错。&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var s string = &quot;hello&quot;
s[0] = 'c'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;但如果真的想要修改怎么办下面的代码可以实现&quot;&gt;但如果真的想要修改怎么办？下面的代码可以实现。&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;s := &quot;hello&quot;
c := []byte(s)  // 将字符串 s 转换为 []byte 类型
c[0] = 'c'
s2 := string(c)  // 再转换回 string 类型
fmt.Printf(&quot;%s\n&quot;, s2)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;go语言中可以使用操作符来连接两个字符串&quot;&gt;Go语言中可以使用“+”操作符来连接两个字符串。&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;s := &quot;hello,&quot;
m := &quot; world&quot;
a := s + m
fmt.Printf(&quot;%s\n&quot;, a)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;修改字符串也可写为&quot;&gt;修改字符串也可写为&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;s := &quot;hello&quot;
s = &quot;c&quot; + s[1:] // 字符串虽不能更改，但可进行切片操作
fmt.Printf(&quot;%s\n&quot;, s)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;如果要声明一个多行的字符串怎么办可以通过反引号来声明&quot;&gt;如果要声明一个多行的字符串怎么办？可以通过&lt;strong&gt;&lt;em&gt;反引号&lt;/em&gt;&lt;/strong&gt;“`”来声明。&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;m := `hello

    world`
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;注意： &lt;strong&gt;反引号“`”括起的字符串为Raw字符串，即字符串在代码中的形式就是打印时的形式，它没有字符转义，换行也将原样输出&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;错误类型&quot;&gt;错误类型&lt;/h2&gt;

&lt;p&gt;Go语言内置有一个error类型，专门用来处理错误信息，Go语言的package里面还专门有一个包errors来处理错误。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;err :=errors.New(&quot;emit macho dwarf: elf header corrupted&quot;)
if err != nil {
    fmt.Print(err)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;一些技巧&quot;&gt;一些技巧&lt;/h2&gt;

&lt;p&gt;分组声明
在Go语言中，同时声明多个常量、变量，或者导入多个包时，可采用分组的方式进行声明。&lt;/p&gt;

&lt;p&gt;例如下面的代码。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import&quot;fmt&quot;
import &quot;os&quot;

const i = 100
const pi = 3.1415
const prefix =&quot;Go_&quot;

var i int
var pi float32
var prefix string
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;可以分组写成如下形式&quot;&gt;可以分组写成如下形式。&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import(
    &quot;fmt&quot;
    &quot;os&quot;
)

const(
    i = 100
    pi = 3.1415
    prefix = &quot;Go_&quot;
)

var(
    i int
    pi float32
    prefix string
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;常量的几点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;除非被显式设置为其他值或iota，每个const分组的第一个常量被默认设置为它的0值.&lt;/li&gt;
  &lt;li&gt;第二及后续的常量被默认设置为它前面那个常量的值，如果前面那个常量的值是iota，则它也被设置为iota.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##iota枚举
Go语言里面有一个关键字iota，这个关键字用来声明enum的时候采用，它默认开始值是0，每调用一次加1。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;const(
    x = iota // x == 0
    y = iota // y == 1
    z = iota // z == 2
    w  //常量声明省略值时，默认和之前一个值的字面相同。这里隐式地说w = iota，因此w== 3。其实上面y和z可同样不用&quot;= iota&quot;
)
const v = iota // 每遇到一个const关键字，iota就会重置，此时v == 0 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;go语言程序设计的一些规则&quot;&gt;Go语言程序设计的一些规则&lt;/h2&gt;

&lt;p&gt;Go语言之所以简洁，是因为它有一些默认的行为。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;大写字母开头的变量是可导出的，即其他包可以读取，是公用变量；小写字母开头的不可导出，是私有变量。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;大写字母开头的函数也是一样，相当于class中带public关键词的公有函数；小写字母开头就是有private关键词的私有函数。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;参考&quot;&gt;参考&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.csdn.net/broadview2006/article/details/8919014&quot;&gt;&lt;strong&gt;go语言基础&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2015/12/28/go-basic-learn.html</link>
    <guid>http://huyongde.github.io/2015/12/28/go-basic-learn</guid>
    <pubDate>Mon, 28 Dec 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>go语言 array, slice , map 简单介绍</title>
    <description>&lt;p&gt;&lt;a href=&quot;http://www.cnblogs.com/yjf512/archive/2012/06/14/2549929.html&quot;&gt;&lt;strong&gt;&lt;em&gt;参考&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;1-数组-array&quot;&gt;1. 数组 array&lt;/h3&gt;

&lt;p&gt;array是固定长度的数组，这个和C语言中的数组是一样的，使用前必须确定数组长度。&lt;/p&gt;

&lt;p&gt;但是和C中的数组相比，又是有一些不同的：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Go中的数组是值传递类型，换句话说，如果你将一个数组赋值给另外一个数组，那么，实际上就是将整个数组拷贝一份。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;如果Go中的数组作为函数的参数，那么实际传递的参数是一份数组的拷贝，而不是数组的指针, 是值传递而不是引用传递。
 这个和C要区分开。因此，在Go中如果将数组作为函数的参数传递的话，那效率就肯定没有传递指针高了。好坑的感觉!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;array的长度也是Type的一部分，这样就说明[10]int和[20]int是不一样的。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h5 id=&quot;array的结构如下&quot;&gt;array的结构如下:&lt;/h5&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;len&lt;/th&gt;
      &lt;th&gt;int&lt;/th&gt;
      &lt;th&gt;int&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;len表示数组的长度，后面是存储的实际数据&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;2-切片-slice&quot;&gt;2. 切片 slice&lt;/h3&gt;

&lt;p&gt;可以参考本站另一个博文  &lt;a href=&quot;http://huyongde.github.io/2015/12/25/go-slice.html&quot;&gt;&lt;em&gt;slice 学习&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;这里再介绍两点：&lt;/p&gt;

&lt;h4 id=&quot;21-slice长度可变&quot;&gt;2.1 slice长度可变&lt;/h4&gt;

&lt;p&gt;定义完一个slice变量之后，不需要为它的容量而担心，你随时可以往slice里面加数据&lt;/p&gt;

&lt;p&gt;比如：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;v:=[]int{}
v=append(v,  10)
//这里附带说一下，slice和array的写法很容易混
v:=[2]string{&quot;arr&quot;, &quot;arr&quot;} //这个是array
m:=[]string{&quot;s&quot;,&quot;s&quot;} //这个是slice
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;要记住：array 定长slice不定长,array 定长slice不定长,array 定长slice不定长….  ，重要的事情说多变。&lt;/p&gt;

&lt;h4 id=&quot;22slice是引用传递-是指针&quot;&gt;2.2slice是引用传递, 是指针&lt;/h4&gt;

&lt;p&gt;指针比值可就小多了，因此，我们将slice作为函数参数传递比将array作为函数参数传递会更有性能。
slice是一个指针，它指向的是一个array结构，它有两个基本函数len和cap。&lt;/p&gt;

&lt;p&gt;slice是一个带有point（指向数组的指针），Len（数组中实际有值的个数），Cap（数组的容量）&lt;/p&gt;

&lt;p&gt;append函数就理解为往slice中加入一个值，如果未达到容量（len&amp;lt;cap）那么就直接往数组中加值，
如果达到容量（len = cap）那么就新增一倍的新元素空间，再赋值。&lt;/p&gt;

&lt;h3 id=&quot;3-map-结构&quot;&gt;3. map 结构&lt;/h3&gt;

&lt;p&gt;map结构也经常常用，它和php中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;array（）&lt;/code&gt;几乎一模一样，是一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key-value&lt;/code&gt;的hash结构。&lt;/p&gt;

&lt;p&gt;key可以是除了func类型，array,slice,map类型之外的类型。&lt;/p&gt;

&lt;p&gt;使用例子如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fmt.Println(&quot;learn map&quot;)
m := map[string]string{}
var m1 = map[int]string{}
m[&quot;key1&quot;] = &quot;value1&quot;
fmt.Println(m)
m1[1] = &quot;int key , string value&quot;
fmt.Println(m1)
var m2 = map[int]int{}
m2[1] = 2
fmt.Println(m2)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;输出结果:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;learn map
map[key1:value1]
map[1:int key , string value]
map[1:2]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
    <link>http://huyongde.github.io/2015/12/26/golang-array-slice-map-introduction.html</link>
    <guid>http://huyongde.github.io/2015/12/26/golang-array-slice-map-introduction</guid>
    <pubDate>Sat, 26 Dec 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>go slice(切片)学习</title>
    <description>&lt;p&gt;&lt;a href=&quot;http://www.tuicool.com/articles/QrymYz&quot;&gt;&lt;strong&gt;&lt;em&gt;参考&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;##slice简介
slice切片是对底层数组Array的封装，在内存中的存储本质就是数组，体现为连续的内存块.&lt;/p&gt;

&lt;p&gt;##slice 与 array的关系&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Go语言中的数组定义之后，长度就已经固定了，在使用过程中并不能改变其长度，而Slice就可以看做一个长度可变的数组进行使用，&lt;/li&gt;
  &lt;li&gt;数组在使用的过程中都是值传递，将一个数组赋值给一个新变量或作为方法参数传递时，是将源数组在内存中完全复制了一份，而不是引用源数组在内存中的地址，为了满足内存空间的复用和数组元素的值的一致性的应用需求，Slice出现了，每个Slice都是都源数组在内存中的地址的一个引用，源数组可以衍生出多个Slice，Slice也可以继续衍生Slice，而内存中，始终只有源数组，也有例外，最后会介绍。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##如何定义slice&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;直接定义
直接上例子&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var slice1 = []int{100, 200}
fmt.Println(slice1)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;通过数组生成切片slice, 例子如下&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
s := a[3:6]
fmt.Println(s)  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;定义一个数组a,并截取下标3到6（包括3,不包括6）的元素构建slice s.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;make定义切片slice, 例子如下:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;s := make([]int, 10)
fmt.Println(s)
fmt.Printf(&quot;len s %d, cap s %d\n&quot;, len(s), cap(s))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;make 函数第一个参数是构建slice的类型，第二个参数是slice的长度，第三个参数是slice的容量，默认是第二个参数的值&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;##slice 长度(len) 和 容量（cap)&lt;/p&gt;

&lt;p&gt;**slice有两个比较混淆的概念，就是长度和容量. **&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;何谓长度？这个长度跟数组的长度是一个概念，即在内存中进行了初始化实际存在的元素的个数。&lt;/li&gt;
  &lt;li&gt;何谓容量？如果通过make函数创建Slice的时候指定了容量参数，那内存管理器会根据指定的容量的值先划分一块内存空间，然后才在其中存放有数组元素，多余部分处于空闲状态，在Slice上追加元素的时候，首先会放到这块空闲的内存中，如果添加的参数个数超过了容量值，内存管理器会重新划分一块容量值为原容量值*2大小的内存空间，依次类推。这个机制的好处在能够提升运算性能，因为内存的重新划分会降低性能。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;######看如下例子&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;s := make([]int, 10)
fmt.Println(s)
fmt.Printf(&quot;len s %d, cap s %d\n&quot;, len(s), cap(s))
s = append(s, 100, 200, 300, 400)
fmt.Println(s)
fmt.Printf(&quot;len s %d, cap s %d\n&quot;, len(s), cap(s))

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;make构建一个slice s,长度和容量都是10， 执行append之后，长度变成13， 容量变成20。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;##slice 引用数据类型&lt;/p&gt;

&lt;p&gt;slice 是源数组的一个引用，改变slice的值，将会改变源数组的值。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var a = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println(a)
s1 := a[3:6]
fmt.Println(s1)
fmt.Printf(&quot;len s1 %d, cap s1 %d\n&quot;, len(s1), cap(s1))
s1[2] = 200
fmt.Println(a)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;程序输出结果如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[1 2 3 4 5 6 7 8 9 0]
[4 5 6]
len s1 3, cap s1 7
[1 2 3 4 5 200 7 8 9 0]

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;slice s1是通过数据a 构建的切片，当改变s1的下标为2的元素的值时，数组a下标为5的元素的值也被改变&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;##slice 切片非引用的情况
Slice是引用类型，指向的都是内存中的同一块内存，不过在实际应用中，有的时候却会发生“意外”
这种情况只有在像切片append元素的时候出现，Slice的处理机制是这样的，&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;当Slice的容量还有空闲的时候，append进来的元素会直接使用空闲的容量空间;&lt;/li&gt;
  &lt;li&gt;一旦append进来的元素个数超过了原来指定容量值的时候，内存管理器就是重新开辟一个更大的内存空间，用于存储多出来的元素，并且会将原来的元素复制一份，放到这块新开辟的内存空间,这样就不是引用了。&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var a = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println(a)
s1 := a[3:6]
fmt.Println(s1)
fmt.Printf(&quot;len s1 %d, cap s1 %d\n&quot;, len(s1), cap(s1))
fmt.Printf(&quot;init address: %p\n&quot;, s1)
s1 = append(s1, 1)
fmt.Printf(&quot;in cap len s1 %d, cap s1 %d\n&quot;, len(s1), cap(s1))
fmt.Printf(&quot;in cap, address: %p\n&quot;, s1)
s1 = append(s1, 1, 2, 3, 4, 4, 5)
fmt.Printf(&quot;out cap len s1 %d, cap s1 %d\n&quot;, len(s1), cap(s1))
fmt.Printf(&quot;out cap, address: %p\n&quot;, s1)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;#####程序输出结果:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[1 2 3 4 5 6 7 8 9 0]
[4 5 6]
len s1 3, cap s1 7
init address: 0xc8200860b8
in cap len s1 4, cap s1 7
in cap, address: 0xc8200860b8
out cap len s1 10, cap s1 14
out cap, address: 0xc82006c070
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;可以看到切片s1第一次append之后，没有超过cap, 还是引用,s1 的地址没变； 第二次append之后，超过了原先预分配的cap, 变成了值复制，s1地址变了。&lt;/strong&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/12/25/go-slice.html</link>
    <guid>http://huyongde.github.io/2015/12/25/go-slice</guid>
    <pubDate>Fri, 25 Dec 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>nginx lua 学习</title>
    <description>&lt;p&gt;&lt;a href=&quot;http://www.ttlsa.com/nginx/nginx-lua/&quot;&gt;&lt;strong&gt;参考&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;11-介绍&quot;&gt;1.1. 介绍&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;ngx_lua – 把lua语言嵌入nginx中,使其支持lua来快速开发基于nginx下的业务逻辑
该模块不在nginx源码包中，需自行下载编译安装。使用lua 5.1（目前不支持lua 5.2） 或 luajit 2.0 。
添加lua支持后，开发复杂的模块，周期快，依然是100%异步非阻塞。&lt;/li&gt;
  &lt;li&gt;ngx_lua 哪些人在用:
淘宝、腾讯财经、网易财经、360、去哪儿网等
CloudFlare, CNN, Wingify, Reblaze, Turner, Broadcasting System&lt;/li&gt;
  &lt;li&gt;该项目主要开发者：
chaoslawful Taobao, Alibaba Grp.
agentzh CloudFlare
https://github.com/chaoslawful/lua-nginx-module&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;12-安装&quot;&gt;1.2. 安装&lt;/h3&gt;
&lt;h4 id=&quot;121-安装jit平台&quot;&gt;1.2.1. 安装JIT平台&lt;/h4&gt;

&lt;p&gt;通常，程序有两种运行方式：静态编译与动态直译。
静态编译的程序在执行前全部被翻译为机器码，而动态直译执行的则是一句一句边运行边翻译。
即时编译(Just-In-Time Compiler)则混合了这二者，一句一句编译源代码，但是会将翻译过的代码缓存起来以降低性能损耗。
JAVA、.NET 实现都使用即时编译以提供高速的代码执行。&lt;/p&gt;

&lt;p&gt;注意：&lt;/p&gt;

&lt;p&gt;&lt;em&gt;** 在nginx.conf中添加”lua_code_cache on/off”，来开启是否将代码缓存，所以每次变更”.lua”文件时，必须reload nginx才可生效。仅针对”set_by_lua_file, content_by_lua_file, rewrite_by_lua_file, and access_by_lua_file”有效, 因为其他为写在配置文件中，更改代码也必须reload nginx。在生产环境下，不能禁用cache。同时在lua代码中使用”dofile” 或 “loadfie” 来加载外部lua脚本将不会对它进行缓存，应该使用”require”来代替。禁用cache，当且仅当在调式代码下。 **&lt;/em&gt;&lt;/p&gt;

&lt;h5 id=&quot;luajit&quot;&gt;LuaJIT&lt;/h5&gt;
&lt;p&gt;luajit 是一个利用JIT编译技术把Lua脚本直接编译成机器码由CPU运行
版本：2.0 与 2.1
当前稳定版本为 2.0。
2.1为版本与ngx_lua将有较大性能提升，主要是CloudFlare公司对luajit的捐赠。
FFI库，是LuaJIT中最重要的一个扩展库。&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;它允许从纯Lua代码调用外部C函数，使用C数据结构;&lt;/li&gt;
  &lt;li&gt;就不用再像Lua标准math库一样，编写Lua扩展库;&lt;/li&gt;
  &lt;li&gt;把开发者从开发Lua扩展C库（语言/功能绑定库）的繁重工作中释放出来;
下载编译&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget -c http://luajit.org/download/LuaJIT-2.0.2.tar.gz
tar xzvf LuaJIT-2.0.2.tar.gz
cd LuaJIT-2.0.2
make install PREFIX=/usr/local/luajit
echo &quot;/usr/local/luajit/lib&quot; &amp;gt; /etc/ld.so.conf.d/usr_local_luajit_lib.conf
ldconfig
#注意环境变量!
export LUAJIT_LIB=/usr/local/luajit/lib
export LUAJIT_INC=/usr/local/luajit/include/luajit-2.0

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;122-ndk与lua_module&quot;&gt;1.2.2. NDK与Lua_module&lt;/h4&gt;

&lt;p&gt;NDK(Nginx Development Kit)模块是一个拓展Nginx服务器核心功能的模块
第三方模块开发可以基于它来快速实现
NDK提供函数和宏处理一些基本任务，减轻第三方模块开发的代码量。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget -c https://github.com/simpl/ngx_devel_kit/archive/v0.2.18.tar.gz
wget -c https://github.com/chaoslawful/lua-nginx-module/archive/v0.8.6.tar.gz
tar xzvf v0.2.18
tar xzvf v0.8.6

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;123-编译安装nginx&quot;&gt;1.2.3. 编译安装Nginx&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget -c http://nginx.org/download/nginx-1.4.2.tar.gz
tar xzvf nginx-1.4.2.tar.gz
cd nginx-1.4.2
./configure --add-module=../ngx_devel_kit-0.2.18/ --add-module=../lua-nginx-module-0.8.6/
make
make install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;13-嵌入lua后&quot;&gt;1.3. 嵌入Lua后&lt;/h3&gt;
&lt;h4 id=&quot;131-检测版本&quot;&gt;1.3.1. 检测版本&lt;/h4&gt;
&lt;p&gt;自己编译官方的 nginx 源码包，只需事前指定 LUAJIT_INC 和 LUAJIT_LIB 这两个环境变量。
验证你的 LuaJIT 是否生效，可以通过下面这个接口：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;location = /lua-version {  
    content_by_lua ' 
            if jit then 
                    ngx.say(jit.version) 
                else 
                    ngx.say(_VERSION) 
            end 
        '; 
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果使用的是标准 Lua，访问 /lua-version 应当返回响应体 Lua 5.1
如果是 LuaJIT 则应当返回类似 LuaJIT 2.0.2 这样的输出。
不要使用标准lua，应当使用luajit, 后者的效率比前者高多了。
也可以直接用 ldd 命令验证是否链了 libluajit-5.1 这样的 .so 文件，例如：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[root@limq5 sbin]# ldd nginx | grep lua
libluajit-5.1.so.2 =&amp;gt; /usr/local/luajit/lib/libluajit-5.1.so.2 (0x00007f48e408b000)
[root@limq5 sbin]#

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;132-helloworld&quot;&gt;1.3.2. Hello,World&lt;/h4&gt;
&lt;p&gt;在nginx.conf中的service添加一个location。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;location = /test {
       content_by_lua '
           ngx.say(&quot;Hello World&quot;)
       ngx.log(ngx.ERR, &quot;err err err&quot;)
       ';
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;用户访问 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost/test&lt;/code&gt; 将会打印出“Hello World”内容。
ngx.say 是 lua 显露給模块的接口。
类似的有 ngx.log(ngx.DEBUG, “”),可以在error.log输出调试信息。
另外也可以调用外部脚本，如同我们写php、jsp应用时,业务脚本单独组织在.php或.jsp文件中一样&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;location = /test2 {
       content_by_lua_file conf/lua/hello.lua;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;文件hello.lua内容如下：&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ngx.say(&quot;Hello World&quot;)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这里的脚本可以任意复杂,也可以使用Lua 自己的库&lt;/p&gt;

&lt;p&gt;lua可用&lt;a href=&quot;http://luarocks.org/repositories/rocks/&quot;&gt;模块列表&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;安装类似yum，它也有一个仓库:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;luarocks install luafilesystem&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;运行上面命令后，会编译一个 “lfs.so”, 文件，拷贝文件到nginx定义的LUA_PATH中，然后引用该
库，就可调用其中函数。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;LUA_PATH:
lua_package_path ‘/opt/17173/nginx-ds/conf/lua/?.lua;;’
lua_package_cpath ‘/opt/17173/nginx-ds/conf/lua/lib/?.so;/usr/local/lib/?.?;;’;
其中”;;”代表原先查找范围。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;133-同步形式异步执行&quot;&gt;1.3.3. 同步形式，异步执行&lt;/h4&gt;
&lt;p&gt;我们假定,同时要访问多个数据源，而且,查询是没有依赖关系,那我们就可以同时发出请求
这样我总的延时, 是我所有请求中最慢的一个所用时间,而不是原先的所有请求用时的叠加&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;location = /api {
       content_by_lua '
           local res1, res2, res3 =
               ngx.location.capture_multi{
                   {&quot;/memc&quot;}, {&quot;/mysql&quot;}, {&quot;/postgres&quot;}
               }
           ngx.say(res1.body, res2.body, res3.body)
       ';
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ngx.location.capture&lt;/code&gt; 无法跨server进行处理, 只能在同一个server下的不同location。&lt;/p&gt;

&lt;h3 id=&quot;14-nginx与lua执行顺序&quot;&gt;1.4. Nginx与Lua执行顺序&lt;/h3&gt;
&lt;h4 id=&quot;141-nginx顺序&quot;&gt;1.4.1. Nginx顺序&lt;/h4&gt;
&lt;p&gt;Nginx 处理每一个用户请求时，都是按照若干个不同阶段（phase）依次处理的，而不是根据配置文件上的顺序。
Nginx 处理请求的过程一共划分为 11 个阶段，按照执行顺序依次是&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;post-read、server-rewrite、find-config、rewrite、post-rewrite、 
preaccess、access、post-access、try-files、content、log.

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;post-read:
读取请求内容阶段
Nginx读取并解析完请求头之后就立即开始运行
例如模块 ngx_realip 就在 post-read 阶段注册了处理程序，它的功能是迫使 Nginx 认为当前请求的来源地址是指定的某一个请求头的值。&lt;/li&gt;
  &lt;li&gt;server-rewrite
Server请求地址重写阶段
当 ngx_rewrite 模块的set配置指令直接书写在 server 配置块中时，基本上都是运行在 server-rewrite 阶段&lt;/li&gt;
  &lt;li&gt;find-config
配置查找阶段
这个阶段并不支持 Nginx 模块注册处理程序，而是由 Nginx 核心来完成当前请求与 location 配置块之间的配对工作。&lt;/li&gt;
  &lt;li&gt;rewrite
Location请求地址重写阶段
当 ngx_rewrite 模块的指令用于 location 块中时，便是运行在这个 rewrite 阶段。
另外，ngx_set_misc(设置md5、encode_base64等) 模块的指令，还有 ngx_lua 模块的 set_by_lua 指令和 rewrite_by_lua 指令也在此阶段。&lt;/li&gt;
  &lt;li&gt;post-rewrite
请求地址重写提交阶段
由 Nginx 核心完成 rewrite 阶段所要求的“内部跳转”操作,如果 rewrite 阶段有此要求的话。&lt;/li&gt;
  &lt;li&gt;preaccess
访问权限检查准备阶段
标准模块 ngx_limit_req 和 ngx_limit_zone 就运行在此阶段，前者可以控制请求的访问频度，而后者可以限制访问的并发度。&lt;/li&gt;
  &lt;li&gt;access
访问权限检查阶段
标准模块 ngx_access、第三方模块 ngx_auth_request 以及第三方模块 ngx_lua 的 access_by_lua 指令就运行在这个阶段。
配置指令多是执行访问控制性质的任务，比如检查用户的访问权限，检查用户的来源 IP 地址是否合法&lt;/li&gt;
  &lt;li&gt;post-access
访问权限检查提交阶段
主要用于配合 access 阶段实现标准 ngx_http_core 模块提供的配置指令 satisfy 的功能。
satisfy all(与关系)
satisfy any(或关系)&lt;/li&gt;
  &lt;li&gt;try-files
配置项try_files处理阶段
专门用于实现标准配置指令 try_files 的功能
如果前 N-1 个参数所对应的文件系统对象都不存在，try-files 阶段就会立即发起“内部跳转”到最后一个参数（即第 N 个参数）所指定的 URI.&lt;/li&gt;
  &lt;li&gt;content
内容产生阶段
Nginx 的 content 阶段是所有请求处理阶段中最为重要的一个，因为运行在这个阶段的配置指令一般都肩负着生成“内容”并输出 HTTP 响应的使命。&lt;/li&gt;
  &lt;li&gt;log
日志模块处理阶段
记录日志
淘宝有开放一个nginx开发手册，里面包含很多有用的资料
http://tengine.taobao.org/book/
作者的google论坛：
https://groups.google.com/forum/#!forum/openresty&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;142-lua顺序&quot;&gt;1.4.2. Lua顺序&lt;/h4&gt;
&lt;p&gt;Nginx下Lua处理阶段与使用范围：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;init_by_lua            http
set_by_lua             server, server if, location, location if
rewrite_by_lua         http, server, location, location if
access_by_lua          http, server, location, location if
content_by_lua         location, location if
header_filter_by_lua   http, server, location, location if
body_filter_by_lua     http, server, location, location if
log_by_lua             http, server, location, location if
timer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;init_by_lua
在nginx重新加载配置文件时，运行里面lua脚本，常用于全局变量的申请。
例如lua_shared_dict共享内存的申请，只有当nginx重起后，共享内存数据才清空，这常用于统计。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;set_by_lua:
设置一个变量，常用与计算一个逻辑，然后返回结果
该阶段不能运行Output API、Control API、Subrequest API、Cosocket API&lt;/li&gt;
  &lt;li&gt;rewrite_by_lua:
在access阶段前运行，主要用于rewrite&lt;/li&gt;
  &lt;li&gt;access_by_lua:
主要用于访问控制，能收集到大部分变量，类似status需要在log阶段才有。
这条指令运行于nginx access阶段的末尾，因此总是在 allow 和 deny 这样的指令之后运行，虽然它们同属 access 阶段。&lt;/li&gt;
  &lt;li&gt;content_by_lua:
阶段是所有请求处理阶段中最为重要的一个，运行在这个阶段的配置指令一般都肩负着生成内容（content）并输出HTTP响应。&lt;/li&gt;
  &lt;li&gt;header_filter_by_lua:
一般只用于设置Cookie和Headers等
该阶段不能运行Output API、Control API、Subrequest API、Cosocket API&lt;/li&gt;
  &lt;li&gt;body_filter_by_lua:
一般会在一次请求中被调用多次, 因为这是实现基于 HTTP 1.1 chunked 编码的所谓“流式输出”的。
该阶段不能运行Output API、Control API、Subrequest API、Cosocket API&lt;/li&gt;
  &lt;li&gt;log_by_lua:
该阶段总是运行在请求结束的时候，用于请求的后续操作，如在共享内存中进行统计数据,如果要高精确的数据统计，应该使用body_filter_by_lua。
该阶段不能运行Output API、Control API、Subrequest API、Cosocket API&lt;/li&gt;
&lt;/ul&gt;
</description>
    <link>http://huyongde.github.io/2015/12/24/ngx-lua-learn.html</link>
    <guid>http://huyongde.github.io/2015/12/24/ngx-lua-learn</guid>
    <pubDate>Thu, 24 Dec 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>nginx 的 sendfile tcp_nodelay  tcp_nopush 配置详解</title>
    <description>&lt;h2 id=&quot;sendfile&quot;&gt;sendfile&lt;/h2&gt;

&lt;p&gt;现在流行的web 服务器里面都提供 sendfile 选项用来提高服务器性能，那到底 sendfile是什么，怎么影响性能的呢？&lt;/p&gt;

&lt;p&gt;sendfile实际上是 Linux2.0+以后的推出的一个系统调用，web服务器可以通过调整自身的配置来决定是否利用 sendfile这个系统调用。&lt;/p&gt;

&lt;h4 id=&quot;先来看一下不用-sendfile的传统网络传输过程&quot;&gt;先来看一下不用 sendfile的传统网络传输过程：&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;read(file,tmp_buf, len);
write(socket,tmp_buf, len);
硬盘 &amp;gt;&amp;gt; kernel buffer &amp;gt;&amp;gt; user buffer&amp;gt;&amp;gt; kernel socket buffer &amp;gt;&amp;gt;协议栈
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;**一般来说一个网络应用是通过读硬盘数据，然后写数据到socket 来完成网络传输的。&lt;/p&gt;

&lt;p&gt;上面2行用代码解释了这一点，不过上面2行简单的代码掩盖了底层的很多操作。来看看底层是怎么执行上面2行代码的:**&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;系统调用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt;产生一个上下文切换：从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user mode&lt;/code&gt; 切换到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel mode&lt;/code&gt;，然后 DMA 执行拷贝，把文件数据从硬盘读到一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel buffer&lt;/code&gt; 里。&lt;/li&gt;
  &lt;li&gt;数据从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel buffer&lt;/code&gt;拷贝到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user buffer&lt;/code&gt;，然后系统调用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt; 返回，这时又产生一个上下文切换：从&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel mode&lt;/code&gt; 切换到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user mode&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;系统调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write()&lt;/code&gt;产生一个上下文切换：从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user mode&lt;/code&gt;切换到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel mode&lt;/code&gt;，然后把步骤2读到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user buffer&lt;/code&gt;的数据拷贝到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel buffer&lt;/code&gt;（数据第2次拷贝到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel buffer&lt;/code&gt;），不过这次是个不同的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel buffer&lt;/code&gt;，这个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer&lt;/code&gt;和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socket&lt;/code&gt;相关联。&lt;/li&gt;
  &lt;li&gt;系统调用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write()&lt;/code&gt;返回，产生一个上下文切换：从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel mode&lt;/code&gt; 切换到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user mode&lt;/code&gt;（第4次切换了），然后 DMA 从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel buffer&lt;/code&gt;拷贝数据到协议栈（第4次拷贝了）。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;上面4个步骤有4次上下文切换，有4次拷贝，我们发现如果能减少切换次数和拷贝次数将会有效提升性能。在kernel2.0+ 版本中，系统调用 sendfile() 就是用来简化上面步骤提升性能的。sendfile() 不但能减少切换次数而且还能减少拷贝次数。&lt;/strong&gt;&lt;/p&gt;

&lt;h4 id=&quot;再来看一下用-sendfile来进行网络传输的过程&quot;&gt;再来看一下用 sendfile()来进行网络传输的过程：&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sendfile(socket,file, len);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;硬盘 » kernel buffer (快速拷贝到kernelsocket buffer) »协议栈&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;系统调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sendfile()&lt;/code&gt;通过 DMA把硬盘数据拷贝到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel buffer&lt;/code&gt;，然后数据被 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel&lt;/code&gt;直接拷贝到另外一个与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socket&lt;/code&gt;相关的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel buffer&lt;/code&gt;。这里没有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user mode&lt;/code&gt;和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel mode&lt;/code&gt;之间的切换，在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel&lt;/code&gt;中直接完成了从一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer&lt;/code&gt;到另一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer&lt;/code&gt;的拷贝。&lt;/li&gt;
  &lt;li&gt;DMA 把数据从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel buffer&lt;/code&gt; 直接拷贝给协议栈，没有切换，也不需要数据从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user mode&lt;/code&gt; 拷贝到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel mode&lt;/code&gt;，因为数据就在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel&lt;/code&gt; 里。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;步骤减少了，切换减少了，拷贝减少了，自然性能就提升了。&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;tcp_nopush&quot;&gt;tcp_nopush&lt;/h2&gt;
&lt;p&gt;官方文档:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tcp_nopush
Syntax: tcp_nopush on | off
Default: off
Context: http
server
location
Reference: tcp_nopush
 
This directive permits or forbids the use of the socket options TCP_NOPUSH on FreeBSD or TCP_CORK on Linux. 
This option is only available when using sendfile.
Setting this option causes nginx to attempt to send it’s HTTP response headers in one packet on Linux and FreeBSD 4.x.
You can read more about the TCP_NOPUSH and TCP_CORK socket options here.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;linux 下是tcp_cork, 上面的意思就是说，当使用sendfile函数时，tcp_nopush才起作用，它和指令tcp_nodelay是互斥的。&lt;/p&gt;

&lt;p&gt;tcp_cork是linux下tcp/ip传输的一个标准了，这个标准的大概的意思是，一般情况下，&lt;/p&gt;

&lt;p&gt;在tcp交互的过程中，当应用程序接收到数据包后马上传送出去，不等待，&lt;/p&gt;

&lt;p&gt;而tcp_cork选项是数据包不会马上传送出去，等到数据包最大时，一次性的传输出去，这样有助于解决网络堵塞，已经是默认了。&lt;/p&gt;

&lt;p&gt;也就是说tcp_nopush = on 会设置调用tcp_cork方法，这个也是默认的，结果就是数据包不会马上传送出去，等到数据包最大时，一次性的传输出去，这样有助于解决网络堵塞。&lt;/p&gt;

&lt;p&gt;*以快递投递举例说明一下（以下是我的理解，也许是不正确的），当快递东西时，快递员收到一个包裹，马上投递，&lt;/p&gt;

&lt;p&gt;这样保证了即时性，但是会耗费大量的人力物力，在网络上表现就是会引起网络堵塞.&lt;/p&gt;

&lt;p&gt;而当快递收到一个包裹，把包裹放到集散地，等一定数量后统一投递，这样就是tcp_cork的选项干的事情，这样的话，会最大化的利用网络资源，虽然有一点点延迟。
*&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;对于nginx配置文件中的tcp_nopush，默认就是tcp_nopush,不需要特别指定，这个选项对于www，ftp等大文件很有帮助。&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;tcp_nodelay&quot;&gt;tcp_nodelay&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TCP_NODELAY&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TCP_CORK(tcp_nopush)&lt;/code&gt;基本上控制了包的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nagle化&lt;/code&gt;，agle化在这里的含义是采用Nagle算法把较小的包组装为更大的帧。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;John Nagle&lt;/code&gt;是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Nagle&lt;/code&gt;算法的发明人，后者就是用他的名字来命名的，他在1984年首次用这种方法来尝试解决福特汽车公司的网络拥塞问题（欲了解详情请参看IETF RFC 896）。&lt;/p&gt;

&lt;p&gt;他解决的问题就是所谓的silly window syndrome，中文称“愚蠢窗口症候群”&lt;/p&gt;

&lt;p&gt;，具体含义是，因为普遍终端应用程序每产生一次击键操作就会发送一个包，&lt;/p&gt;

&lt;p&gt;而典型情况下一个包会拥有1个字节的数据载荷以及40个字节长的包头，于是产生&lt;strong&gt;4000%的过载&lt;/strong&gt;，很轻易地就能令网络发生拥塞。&lt;/p&gt;

&lt;p&gt;Nagle化后来成了一种标准并且立即在因特网上得以实现。它现在已经成为缺省配置了.&lt;/p&gt;

&lt;p&gt;但在我们看来，有些场合下把这一选项关掉也是合乎需要的。&lt;/p&gt;

&lt;p&gt;现在让我们假设某个应用程序发出了一个请求，希望发送小块数据。我们可以选择立即发送数据或者等待产生更多的数据然后再一次发送两种策略。&lt;/p&gt;

&lt;p&gt;如果我们马上发送数据，那么交互性的以及客户/服务器型的应用程序将极大地受益。&lt;/p&gt;

&lt;p&gt;如果请求立即发出那么响应时间也会快一些。以上操作可以通过设置套接字的TCP_NODELAY = on 选项来完成，这样就禁用了Nagle 算法。&lt;/p&gt;

&lt;p&gt;另外一种情况则需要我们等到数据量达到最大时才通过网络一次发送全部数据，这种数据传输方式有益于大量数据的通信性能，典型的应用就是文件服务器。&lt;/p&gt;

&lt;p&gt;应用 Nagle算法在这种情况下就会产生问题。但是，如果你正在发送大量数据，你可以设置TCP_CORK选项禁用Nagle化，其方式正好同 TCP_NODELAY相反（TCP_CORK和 TCP_NODELAY是互相排斥的）。&lt;/p&gt;

&lt;h2 id=&quot;参考&quot;&gt;参考&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.2cto.com/os/201306/222745.html&quot;&gt;&lt;em&gt;nginx sendfile tcp_onpush tcp_nodelay 详解&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_core_module.html&quot;&gt;&lt;strong&gt;ngx_http_core_module&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/12/20/nginx-sendfile-tcp_nodelay-tcp_nopush.html</link>
    <guid>http://huyongde.github.io/2015/12/20/nginx-sendfile-tcp_nodelay-tcp_nopush</guid>
    <pubDate>Sun, 20 Dec 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>go 学习资料汇总</title>
    <description>&lt;h2 id=&quot;go-简介&quot;&gt;go 简介&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;go语言是一个开源的项目，让程序员(programmer)能有更多的产出.
go语言简单易懂，执行高效。他有很好的并发机制(concurrency/kən&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kʌrənsɪ/ mechanism /&lt;/code&gt;mekənɪzəm/)
以及很好的垃圾回收(garbage collection). go是一个静态的编译型语言，但他看起来更像动态的解释型语言。
 (PS  翻译的不好，原文请参考&lt;/em&gt;
 &lt;a href=&quot;https://golang.org/doc/&quot;&gt;go doc&lt;/a&gt;)&lt;/p&gt;

&lt;h2 id=&quot;go-安装&quot;&gt;go 安装&lt;/h2&gt;

&lt;p&gt;参考文档 &lt;a href=&quot;https://golang.org/doc/install&quot;&gt;go 安装&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;这里不详细介绍，很简单。&lt;/p&gt;

&lt;h2 id=&quot;go语法学习&quot;&gt;go语法学习&lt;/h2&gt;

&lt;h3 id=&quot;看过的资料&quot;&gt;看过的资料&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://golang.org/doc/code.html&quot;&gt;how to write go code&lt;/a&gt; 介绍了go代码的基本组织结构，有个简单的hello world代码，
可以通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkdir hello;cd hello; export GOPATH=$(pwd); go get github.com/golang/example/hello&lt;/code&gt; 来获得源码,学习到go相关的工具如下：
    &lt;ul&gt;
      &lt;li&gt;go install&lt;/li&gt;
      &lt;li&gt;go test&lt;/li&gt;
      &lt;li&gt;go build&lt;/li&gt;
      &lt;li&gt;go get&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gobyexample.com/&quot;&gt;go example&lt;/a&gt; 通过例子来学习golang&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;正在看的&quot;&gt;正在看的&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://golang.org/ref/spec&quot;&gt;The Go Programming Language Specification&lt;/a&gt; go语言编程规范
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://golang.org/ref/spec#The_zero_value&quot;&gt;zero values&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false for booleans, 0 for integers, 0.0 for floats, &quot;&quot; for strings, and nil for pointers, functions, interfaces, slices, channels, and maps&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://golang.org/pkg/&quot;&gt;golang package&lt;/a&gt; go各个package的介绍,干货多多。&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://tonybai.com/2015/09/17/7-things-you-may-not-pay-attation-to-in-go/&quot;&gt;关于go需要注意的七个细节&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;计划看的资料&quot;&gt;计划看的资料&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://golang.org/doc/effective_go.html&quot;&gt;effective go&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id=&quot;reference&quot;&gt; &lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;参考&quot;&gt;参考&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://golang.org/doc/&quot;&gt;&lt;strong&gt;go doc&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://tour.golang.org/&quot;&gt;&lt;strong&gt;go tour&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2015/12/14/go-learn.html</link>
    <guid>http://huyongde.github.io/2015/12/14/go-learn</guid>
    <pubDate>Mon, 14 Dec 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>英语单词学习</title>
    <description>&lt;p&gt;##go学习涉及到的单词&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;demonstrate /`demənstreɪt/ 介绍说明&lt;/li&gt;
  &lt;li&gt;screencast 视频教程&lt;/li&gt;
  &lt;li&gt;repository /rɪ`pɑːzətɔːri, 仓库代码库&lt;/li&gt;
  &lt;li&gt;hierarchy /`haɪərɑːrki/ 组织结构，阶层&lt;/li&gt;
  &lt;li&gt;mercurial /mɜː`kjʊriəl/  易变的&lt;/li&gt;
  &lt;li&gt;comprise 包括&lt;/li&gt;
  &lt;li&gt;typical /`tipikl/ 通常的&lt;/li&gt;
  &lt;li&gt;distinction /di`stigksn/ 区别&lt;/li&gt;
  &lt;li&gt;specify /spesɪfaɪ/ 指定&lt;/li&gt;
  &lt;li&gt;installation /ˌɪnstə`leɪʃn/ 安装  名词&lt;/li&gt;
  &lt;li&gt;collide /kə`laɪd/ 碰撞，冲突&lt;/li&gt;
  &lt;li&gt;convention /kən’venʃnz/  约定，公约，惯例&lt;/li&gt;
  &lt;li&gt;borrow /’bɑːroʊ, ‘bɒrəʊ/ 借用，借力，从其他语言引入&lt;/li&gt;
  &lt;li&gt;satisfactory /ˌsætɪs’fæktəri/ 满意的&lt;/li&gt;
  &lt;li&gt;straightforward  /ˌstreɪt’fɔːrwərd, ˌstreɪt’fɔːwəd/ 直截了当&lt;/li&gt;
  &lt;li&gt;augment  /ɔːɡ’ment/ 增加，补充，增补&lt;/li&gt;
  &lt;li&gt;specification 规范， language specification 语言规范 /ˌspesɪfɪ’keɪʃn/&lt;/li&gt;
  &lt;li&gt;grammar /’ɡræmər, ‘ɡræmə(r)/ 语法&lt;/li&gt;
  &lt;li&gt;precedence /’presɪdəns/ 优先权&lt;/li&gt;
  &lt;li&gt;quote /kwoʊt, kwəʊt/  引号
    &lt;ul&gt;
      &lt;li&gt;single quote 单引号&lt;/li&gt;
      &lt;li&gt;double quotes 双引号&lt;/li&gt;
      &lt;li&gt;back quote 反引号&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;syntax /’sɪntæks/ 语法&lt;/li&gt;
  &lt;li&gt;lexical /’leksɪkl/ 词法词汇  lexical token 词法标记&lt;/li&gt;
  &lt;li&gt;denote /dɪ’noʊt, dɪ’nəʊt/ 表示&lt;/li&gt;
  &lt;li&gt;enumeration /ɪˌnjuːmə’reɪʃn/  枚举&lt;/li&gt;
  &lt;li&gt;snippet /’snɪpɪt/  片段  code snippet代码片段&lt;/li&gt;
  &lt;li&gt;restriction /rɪ’strɪkʃn/  限制， implementation restriction 实现限制&lt;/li&gt;
  &lt;li&gt;implementation /ˌɪmplɪmen’teɪʃn/  实现，履行&lt;/li&gt;
  &lt;li&gt;decimal /’desɪml/  十进制&lt;/li&gt;
  &lt;li&gt;octal /’ɒktəl, ‘ɒktl/  八进制&lt;/li&gt;
  &lt;li&gt;hex /heks/  十六进制 hexadecimal/ˌheksə’desɪml/&lt;/li&gt;
  &lt;li&gt;vocabulary /və’kæbjəleri, və’kæbjələri/   词汇&lt;/li&gt;
  &lt;li&gt;semicolon /’semikoʊlən, ˌsemi’kəʊlən/  分号&lt;/li&gt;
  &lt;li&gt;teminator /’tɜːməˌneɪtə, ‘tɜːmɪneɪtə/终结者 终结  终结符&lt;/li&gt;
  &lt;li&gt;omit /ə’mɪt/ 忽略&lt;/li&gt;
  &lt;li&gt;integer/’ɪntɪdʒər, ‘ɪntɪdʒə(r)/ 整数&lt;/li&gt;
  &lt;li&gt;occupy/’ɑːkjupaɪ, ‘ɒkjupaɪ/ 占据&lt;/li&gt;
  &lt;li&gt;idiomatic/ˌɪdiə’mætɪk/惯用的&lt;/li&gt;
  &lt;li&gt;reserve/rɪ’zɜːrv, rɪ’zɜːv/ 保留&lt;/li&gt;
  &lt;li&gt;literal/’lɪtərəl/  文字&lt;/li&gt;
  &lt;li&gt;fractional/’frækʃənl/ 分数的，小数的&lt;/li&gt;
  &lt;li&gt;exponent/ɪk’spoʊnənt, ɪk’spəʊnənt/   指数&lt;/li&gt;
  &lt;li&gt;elide/i’laɪd/ 删掉，省略，取消&lt;/li&gt;
  &lt;li&gt;complex number 复数&lt;/li&gt;
  &lt;li&gt;line feed 换行&lt;/li&gt;
  &lt;li&gt;backslash/’bækslæʃ/反斜线&lt;/li&gt;
  &lt;li&gt;synchronization [,sɪŋkrənaɪ’zeɪʃən]  同步&lt;/li&gt;
  &lt;li&gt;asynchronization 异步&lt;/li&gt;
  &lt;li&gt;marshal [‘mɑːʃ(ə)l]  整理排列&lt;/li&gt;
  &lt;li&gt;arbitrary/’ɑːrbətreri, ‘ɑːbɪtrəri/随意的&lt;/li&gt;
  &lt;li&gt;anonymous [ə’nɒnɪməs]  匿名的&lt;/li&gt;
  &lt;li&gt;synchronously [‘siŋkrənəsli]  adv  同步地&lt;/li&gt;
  &lt;li&gt;interleave [ɪntə’liːv] vt, n  交错&lt;/li&gt;
  &lt;li&gt;clause [klɔːz]  从句,子句&lt;/li&gt;
  &lt;li&gt;nano [‘nænəʊ] 纳，毫微， 纳米， 纳秒, 10的九次方&lt;/li&gt;
  &lt;li&gt;epoch [‘iːpɒk; ‘epɒk]  新时代；时间上的一点&lt;/li&gt;
  &lt;li&gt;respective [rɪ’spektɪv] 分别得，各自的&lt;/li&gt;
  &lt;li&gt;elapse [ɪ’læps] 流逝，时间过去。&lt;/li&gt;
  &lt;li&gt;compatible [kəm’pætɪb(ə)l] 兼容的，可共处的，可并立的&lt;/li&gt;
  &lt;li&gt;exec  [ɪg’zek; eg-]  执行程序，执行&lt;/li&gt;
  &lt;li&gt;execute [‘eksɪkjuːt]  实行，执行&lt;/li&gt;
  &lt;li&gt;bundle plugin [‘bʌnd(ə)l]  [plʌgɪn]  捆绑插件&lt;/li&gt;
  &lt;li&gt;bundler 打包机  vim plugin bundler vim 插件打包机&lt;/li&gt;
  &lt;li&gt;permalink [‘pɜːməlɪŋk]  永久链接&lt;/li&gt;
  &lt;li&gt;denial  dɪ’naɪ(ə)l  n.拒绝，否认 ， denial of service attack (dos attack)  拒绝服务攻击&lt;/li&gt;
  &lt;li&gt;pseudo ‘sjuːdəʊ 冒充的， 假的， pseudo header 假头信息&lt;/li&gt;
  &lt;li&gt;urgent 英 ‘ɜːdʒ(ə)nt紧急的，急迫的&lt;/li&gt;
&lt;/ul&gt;

</description>
    <link>http://huyongde.github.io/2015/12/14/english-learn.html</link>
    <guid>http://huyongde.github.io/2015/12/14/english-learn</guid>
    <pubDate>Mon, 14 Dec 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>autoconf  automake 学习</title>
    <description>&lt;h2 id=&quot;简介&quot;&gt;简介&lt;/h2&gt;

&lt;p&gt;介绍如何使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoconf&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;automake&lt;/code&gt; 来为自己开发的c/c++程序生成符合自由软件惯例的Makefile,&lt;/p&gt;

&lt;p&gt;这样的话，就可以和其他的GNU程序一样，通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./configure; make; make install&lt;/code&gt; 把自己的程序安装到linux系统中。&lt;/p&gt;

&lt;h2 id=&quot;helloworld-示例&quot;&gt;helloworld 示例&lt;/h2&gt;

&lt;p&gt;简单的helloworld  c程序，通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoconf&lt;/code&gt; 以及 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;automake&lt;/code&gt;来生成Makefile文件，从而实现通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./configure; make; make install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;来实现生成可执行的二进制文件helloworld&lt;/p&gt;

&lt;h3 id=&quot;需要准备的文件&quot;&gt;需要准备的文件&lt;/h3&gt;

&lt;h4 id=&quot;helloworldc&quot;&gt;helloworld.c&lt;/h4&gt;
&lt;p&gt;内容如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#include&amp;lt;stdio.h&amp;gt;
int main(){
    printf(&quot;hello world!\n&quot;);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;makefileam&quot;&gt;Makefile.am&lt;/h4&gt;
&lt;p&gt;内容如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bin_PROGRAMS=helloworld
hello_SOURCES=helloworld.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;configureac&quot;&gt;configure.ac&lt;/h4&gt;
&lt;p&gt;内容如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;AC_INIT([Helloworld Program], [1.0],
        [huyongde &amp;lt;huyongde@google.com&amp;gt;],
        [helloworld])
AM_INIT_AUTOMAKE
AC_PROG_CC
AC_PROG_INSTALL
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;文件内容简单介绍&quot;&gt;文件内容简单介绍&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Makefile.am是用逻辑语言写的,没有比较明显的执行过程,只是给出了可执行文件和源文件的关系。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;configure.ac 是程序语言，文中每一行都是一个需要执行的命令。&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;AC_INIT 用来初始化configure 脚本。第一个参数是程序的名字，第二个参数是作者以及作者的邮箱，第三个参数是打包的文件的名字。&lt;/li&gt;
      &lt;li&gt;AC_INIT_AUTOMAKE 做了一下我们调用automake需要的相关的初始化。要是自己手动写Makefile.in的话就不需要执行AC_INIT_AUTOMAKE。&lt;/li&gt;
      &lt;li&gt;AC_PROG_CC 检查gcc的版本。&lt;/li&gt;
      &lt;li&gt;AC_PROG_INSTALL&lt;/li&gt;
      &lt;li&gt;AC_CONFIG_FILES 设置脚本configure生成的makefile的文件名。&lt;/li&gt;
      &lt;li&gt;AC_OUTPUT 告诉configure 脚本生成AC_CONFIG_FILES指定的文件。
        &lt;h2 id=&quot;生成configure&quot;&gt;生成configure&lt;/h2&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;按顺序执行如下命令:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;aclocal&lt;/li&gt;
  &lt;li&gt;autoconf&lt;/li&gt;
  &lt;li&gt;touch README AUTHORS NEWS ChangeLog&lt;/li&gt;
  &lt;li&gt;automake -a&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;生成二进制文件&quot;&gt;生成二进制文件&lt;/h2&gt;

&lt;p&gt;按顺序执行如下命令&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./configure&lt;/code&gt; 生成Makefile文件&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make;make install&lt;/code&gt; 生成可执行文件helloworld&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;运行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./helloworld&lt;/code&gt;输出程序的执行结果。&lt;/p&gt;

&lt;h2 id=&quot;参考&quot;&gt;参考&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://autotoolset.sourceforge.net/tutorial.html#Hello-World-revisited&quot;&gt;&lt;strong&gt;Learning the GNU development tools&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.laruence.com/2009/11/18/1154.html&quot;&gt;&lt;strong&gt;鸟哥的autoconf、automake使用详解&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/12/12/autoconf-automake-learn.html</link>
    <guid>http://huyongde.github.io/2015/12/12/autoconf-automake-learn</guid>
    <pubDate>Sat, 12 Dec 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>markdown语法再学习</title>
    <description>&lt;h1 id=&quot;引用&quot;&gt;引用&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;p&gt;这是一个引用&lt;/p&gt;
  &lt;blockquote&gt;
    &lt;p&gt;这是个嵌套引用&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;one&lt;/li&gt;
      &lt;li&gt;two&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/blockquote&gt;

&lt;/blockquote&gt;

&lt;h1 id=&quot;列表&quot;&gt;列表&lt;/h1&gt;

&lt;h2 id=&quot;无序列表&quot;&gt;无序列表&lt;/h2&gt;
&lt;h3 id=&quot;eg1&quot;&gt;eg1&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;one&lt;/li&gt;
  &lt;li&gt;two&lt;/li&gt;
  &lt;li&gt;three&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;eg2&quot;&gt;eg2&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;one&lt;/li&gt;
  &lt;li&gt;two&lt;/li&gt;
  &lt;li&gt;three&lt;/li&gt;
  &lt;li&gt;four&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;eg3&quot;&gt;eg3&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;one&lt;/li&gt;
  &lt;li&gt;three&lt;/li&gt;
  &lt;li&gt;two&lt;/li&gt;
  &lt;li&gt;four&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;有序列表&quot;&gt;有序列表&lt;/h2&gt;
&lt;h3 id=&quot;eg1-1&quot;&gt;eg1&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;onexxxxxxxxxxxxx&lt;/p&gt;

    &lt;p&gt;xxxxxx&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;two&lt;/li&gt;
  &lt;li&gt;three&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;eg2-1&quot;&gt;eg2&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;one&lt;/li&gt;
  &lt;li&gt;two&lt;/li&gt;
  &lt;li&gt;three&lt;/li&gt;
  &lt;li&gt;xxxx&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;代码块&quot;&gt;代码块&lt;/h2&gt;

&lt;h3 id=&quot;eg1-2&quot;&gt;eg1&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;//this is a code block
//line two 
local a = 'xxxx'
ngx.say(a)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;eg2-2&quot;&gt;eg2&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;```
#python block
def func1():
    return 0

```
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;分割线&quot;&gt;分割线&lt;/h2&gt;

&lt;h3 id=&quot;eg1-3&quot;&gt;eg1&lt;/h3&gt;
&lt;hr /&gt;

&lt;h3 id=&quot;eg2-3&quot;&gt;eg2&lt;/h3&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;链接&quot;&gt;链接&lt;/h2&gt;
&lt;p&gt;###inline link
####eg1，inline link 带title的link&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;www.baidu.com&quot; title=&quot;百度&quot;&gt;百度&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&quot;eg2-inline-link-不带title的link&quot;&gt;eg2, inline link 不带title的link&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;huyongde.github.io&quot;&gt;胡永德的github pages&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;reference-link&quot;&gt;reference link&lt;/h3&gt;
&lt;h4 id=&quot;eg1-4&quot;&gt;eg1&lt;/h4&gt;
&lt;p&gt;[百度] [1]
[1]: www.baidu.com “百度”&lt;/p&gt;

&lt;h4 id=&quot;eg2-4&quot;&gt;eg2&lt;/h4&gt;
&lt;p&gt;[baidu link][]
[baidu link]: www.baidu.com&lt;/p&gt;

&lt;h2 id=&quot;重点emphasisemfəsɪs标注&quot;&gt;重点emphasis/’emfəsɪs/标注&lt;/h2&gt;

&lt;h3 id=&quot;简介&quot;&gt;简介&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Markdown treats asterisks (*)/'æstərɪsks/  and underscores (_)  /ˌʌndər'skɔːr, ˌʌndə'skɔː(r)/  as indicators/'ɪndɪkeɪtə/ of emphasis. Text wrapped with one * or _ will be wrapped with an HTML &amp;lt;em&amp;gt; tag; double *’s or _’s will be wrapped with an HTML &amp;lt;strong&amp;gt; tag. E.g., 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;翻译过来是：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;md认为星号asterisk 和下划线 underscore 都是重点标注的指标`indicator`.被星号和下划线包裹起来的文本会被分辨翻译成html的&amp;lt;em&amp;gt;标签和&amp;lt;strong&amp;gt;标签


&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;eg1-one-indicator-presents-italic-text&quot;&gt;eg1: one indicator presents italic text&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;我是个斜体&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;-this is a italic[i’tælik] text-&lt;/p&gt;

&lt;h3 id=&quot;eg2-double-indicators-present-strong-text&quot;&gt;eg2: double indicators present strong text&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;我是个粗体&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;this is a strong text&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;eg3-反斜线backslash转义星号antirisk和下滑线underscore&quot;&gt;eg3: 反斜线backslash转义星号antirisk和下滑线underscore，&lt;/h3&gt;

&lt;p&gt;/* this is not emphasis /*&lt;/p&gt;

&lt;h3 id=&quot;eg-4-strong-italic-text&quot;&gt;eg 4 strong italic text&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;this is a strong italic text&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;代码&quot;&gt;代码&lt;/h2&gt;
&lt;p&gt;下面是一小段代码&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$redis = new redis($redis_conf);&lt;/code&gt;,用来创建和redis交互的实例&lt;/p&gt;

&lt;h2 id=&quot;图片&quot;&gt;图片&lt;/h2&gt;
&lt;p&gt;###eg1
&lt;img src=&quot;http://www.laruence.com/images/gavatar.png?orig=http://tp2.sinaimg.cn/1170999921/50/5606703689/1&quot; alt=&quot;this is a image&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;表格&quot;&gt;表格&lt;/h2&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;You can create tables by assembling a list of words and dividing /də`vaɪd/ them
 with hyphensi /`haɪfn/  - (for the first row), and then separating each column with a pipe |:
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;通过连字符-区分行，通过管道符&lt;/td&gt;
      &lt;td&gt;区分列&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;eg&quot;&gt;eg&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;第一行/列&lt;/th&gt;
      &lt;th&gt;第二行&lt;/th&gt;
      &lt;th&gt;three&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;第二行&lt;/td&gt;
      &lt;td&gt;xxxxx&lt;/td&gt;
      &lt;td&gt;xx&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第三行&lt;/td&gt;
      &lt;td&gt;yyy&lt;/td&gt;
      &lt;td&gt;yyyyy&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;补充&quot;&gt;补充&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Markdown provides backslash escapes for the following characters:

\   backslash
`   backtick
*   asterisk
_   underscore
{}  curly braces
[]  square brackets
()  parentheses
#   hash mark
+   plus sign
-   minus sign (hyphen)
.   dot
!   exclamation mark

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
    <link>http://huyongde.github.io/2015/12/11/markdown-learn.html</link>
    <guid>http://huyongde.github.io/2015/12/11/markdown-learn</guid>
    <pubDate>Fri, 11 Dec 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>http 缓存策略</title>
    <description>&lt;p&gt;##目录&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#type&quot;&gt;web缓存类型&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#header&quot;&gt;缓存相关的header&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#参考&quot;&gt;参考&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id=&quot;type&quot;&gt;&lt;/a&gt;
##web缓存的类型&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;header&quot;&gt;&lt;/a&gt;
##缓存相关的header&lt;/p&gt;

&lt;p&gt;####response header&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;cache-control&lt;/li&gt;
  &lt;li&gt;expires&lt;/li&gt;
  &lt;li&gt;etag
####request header&lt;/li&gt;
  &lt;li&gt;if-modified-since&lt;/li&gt;
  &lt;li&gt;if-none-match&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;####例子&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;如下一个304请求的相关header&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Request Headers&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Accept:image/webp,image/*,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Host:www.cnblogs.com
If-Modified-Since:Sun, 03 Feb 2013 07:04:18 GMT
If-None-Match:&quot;2a497afdc1ce1:0&quot;
Referer:http://www.cnblogs.com/skylar/p/browser-http-caching.html
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Response Headers&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Cache-Control:max-age=86400
Connection:keep-alive
Date:Wed, 09 Dec 2015 07:43:34 GMT
Etag:&quot;2a497afdc1ce1:0&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a id=&quot;参考&quot;&gt;&lt;/a&gt;
##参考&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.cnblogs.com/skylar/p/browser-http-caching.html&quot;&gt;&lt;strong&gt;透过浏览器看HTTP缓存&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.cnblogs.com/skylar/p/browser-http-caching.html&quot;&gt;&lt;strong&gt;HTTP缓存&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2015/12/09/http-cache.html</link>
    <guid>http://huyongde.github.io/2015/12/09/http-cache</guid>
    <pubDate>Wed, 09 Dec 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>unix 查看window开发的代码，如何处理^M特殊字符</title>
    <description>&lt;p&gt;&lt;strong&gt;去除代码中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^M&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;由于mac, linux, windows对行末尾的回车符的处理不一致，会导致在mac或者linux下查看window开发的代码的时候，行末尾存在特殊字符&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^M&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;可以通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dos2unix&lt;/code&gt;来去掉文件的^M&lt;/p&gt;

&lt;p&gt;mac需要安装&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dos2unix&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew install dos2unix&lt;/code&gt;, &lt;a href=&quot;http://brew.sh/index_zh-cn.html&quot;&gt;brew&lt;/a&gt; 是OS X 不可或缺的套件管理工,brew的安装和使用详见&lt;a href=&quot;http://brew.sh/index_zh-cn.html&quot;&gt;&lt;strong&gt;官网&lt;/strong&gt;&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;安装完&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dos2unix&lt;/code&gt;之后，直接&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dos2unix filename&lt;/code&gt;就可以把&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filename&lt;/code&gt;文件中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^M&lt;/code&gt;去掉&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/12/03/dos-mac-window-return.html</link>
    <guid>http://huyongde.github.io/2015/12/03/dos-mac-window-return</guid>
    <pubDate>Thu, 03 Dec 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>写C++遇到的问题</title>
    <description>&lt;p&gt;&lt;strong&gt;写C++测试程序遇到的问题&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;##程序访问网络弹窗提示&lt;/p&gt;

&lt;p&gt;弹窗内容如下:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/防火墙.png&quot; alt=&quot;弹窗&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;解决办法&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;修改项目属性，链接器-&amp;gt;清单文件-&amp;gt;uac执行级别，设置为`requireAdministrator`

              链接器-&amp;gt;清单文件-&amp;gt;uac绕过ui保护,设置为`是`
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;修改后的问题&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;第一次运行还是有弹窗，第二次运行就不会有弹窗了，&lt;strong&gt;问题待解决&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;&lt;em&gt;端的开发可真是折腾人啊，快崩溃了。&lt;/em&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2015/12/03/cplusplus-problem.html</link>
    <guid>http://huyongde.github.io/2015/12/03/cplusplus-problem</guid>
    <pubDate>Thu, 03 Dec 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>架构师培训</title>
    <description>&lt;p&gt;##架构师的能力要求&lt;/p&gt;

&lt;p&gt;###领悟&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;抽象能力&lt;/li&gt;
  &lt;li&gt;逻辑能力&lt;/li&gt;
  &lt;li&gt;学习能力&lt;/li&gt;
  &lt;li&gt;表达能力&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###领域&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;足够的知识积累
    &lt;ul&gt;
      &lt;li&gt;对目标系统进行恰当的抽象。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###领袖
    在方向决策以及团队向心力上起主导作用,主要体现在团队领导上面。&lt;/p&gt;

&lt;p&gt;##若偏则费，重在平衡&lt;/p&gt;

&lt;p&gt;##架构设计的基本原则和方法&lt;/p&gt;

&lt;p&gt;架构师设计产生的一个子集，架构更关注系统整体性方面的需求。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;功能性
    &lt;ul&gt;
      &lt;li&gt;模块化&lt;/li&gt;
      &lt;li&gt;可构建性&lt;/li&gt;
      &lt;li&gt;可测试性&lt;/li&gt;
      &lt;li&gt;生态系统&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;非功能性
    &lt;ul&gt;
      &lt;li&gt;可靠性&lt;/li&gt;
      &lt;li&gt;性能&lt;/li&gt;
      &lt;li&gt;安全性&lt;/li&gt;
      &lt;li&gt;可扩展性&lt;/li&gt;
      &lt;li&gt;可维护性&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###设计好坏的指标
    * 高内聚
    * 低耦合&lt;/p&gt;

&lt;p&gt;####内聚&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cohesion&lt;/code&gt;关注功能聚集是否正确性
####耦合&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;coupling&lt;/code&gt;关注模块间的独立性&lt;/p&gt;

&lt;p&gt;###耦合
如下，耦合度从高到低:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;实现类   &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;低&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;接口&lt;/li&gt;
  &lt;li&gt;服务&lt;/li&gt;
  &lt;li&gt;消息&lt;/li&gt;
  &lt;li&gt;数据     &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;高&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##各项能力&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;需求分析能力
    &lt;ul&gt;
      &lt;li&gt;需求搜集&lt;/li&gt;
      &lt;li&gt;分析&lt;/li&gt;
      &lt;li&gt;记录&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###需求分析方法
    * 抽象法
    * 面向对象&lt;/p&gt;

&lt;p&gt;###工具&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;UML 用列图&lt;/li&gt;
  &lt;li&gt;原型设计工具
###产出&lt;/li&gt;
  &lt;li&gt;用例图&lt;/li&gt;
  &lt;li&gt;原型图&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##基础设计能力&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;面向对象设计&lt;/li&gt;
  &lt;li&gt;##建构设计能力&lt;/li&gt;
  &lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##SOA 架构
面向服务架构&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service-Oriented Architecture&lt;/code&gt;(SOA)
###SOA的优势&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;行业规范，巨头支持&lt;/li&gt;
  &lt;li&gt;丰富的工具和实践文档&lt;/li&gt;
  &lt;li&gt;贴合业务实际情况&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###如何应用SOA&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;制定服务所用的规范&lt;/li&gt;
  &lt;li&gt;SOA核心在于设计的合理的设计&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##restful架构&lt;/p&gt;

&lt;p&gt;面向资源的开发架构 
###优点
    结构清晰，符合标准， 易于理解， 扩展方便&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;规范化了资源（URL）的定义方案。&lt;/li&gt;
  &lt;li&gt;支持http资源协商机制，&lt;/li&gt;
  &lt;li&gt;资源即 api&lt;/li&gt;
  &lt;li&gt;官方规范&lt;/li&gt;
  &lt;li&gt;成熟的产品支持&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##微服务架构设计&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/11/30/architect-introduction.html</link>
    <guid>http://huyongde.github.io/2015/11/30/architect-introduction</guid>
    <pubDate>Mon, 30 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>chrome浏览器的相关插件</title>
    <description>&lt;p&gt;####user agent switcher&lt;/p&gt;

&lt;p&gt;可以设置发起http请求用到user-agent.&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/11/29/chrome-plugins.html</link>
    <guid>http://huyongde.github.io/2015/11/29/chrome-plugins</guid>
    <pubDate>Sun, 29 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>为浏览器添加vim的快捷键--for vimmer</title>
    <description>&lt;p&gt;###目录&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#简介&quot;&gt;简介&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#chrome&quot;&gt;chrome浏览器&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#firefox&quot;&gt;firefox浏览器&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id=&quot;简介&quot;&gt;&lt;/a&gt;
##简介&lt;/p&gt;

&lt;p&gt;好长一段时间都在用firefox(因为没有个靠谱的vpn,没法用chrome相关功能，包括扩展更新),&lt;/p&gt;

&lt;p&gt;最近折腾好了vpn，可以用起来google的相关功能了。&lt;/p&gt;

&lt;p&gt;想知道怎么折腾vpn的移步&lt;a href=&quot;http://huyongde.github.io/2015/11/24/goout-see-world.html&quot;&gt;翻墙看世界&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;对于vimmer来说，vim的各种快捷键想移植到各个用到的东西上，比如chrome浏览器，visual studio， 有道云笔记(这个暂时还没有插件)等。&lt;/p&gt;

&lt;p&gt;下面介绍下如何在chrome和firefox中使用vim的快捷键&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;chrome&quot;&gt;&lt;/a&gt;
##chrome浏览器&lt;/p&gt;

&lt;p&gt;需要安装chrome的插件(需要翻墙奥)vrome，相关资料如下:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;chrome-extension://godjoomfiimiddapohpmfklhgmbfffjj/background/html/options.html#dashboard&quot;&gt;vrome主页&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/jinzhu/vrome&quot;&gt;vrome github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/vrome/godjoomfiimiddapohpmfklhgmbfffjj&quot;&gt;vrome chrome插件安装&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;chrome-extension://godjoomfiimiddapohpmfklhgmbfffjj/background/html/options.html#setting&quot;&gt;vrome rc配置&lt;/a&gt; 和vimrc类似可以配置自己的快捷键&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/jinzhu/vrome/wiki/vromerc-example-file&quot;&gt;vromerc 示例&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/jinzhu/vrome/wiki&quot;&gt;vrome wiki&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;###简单的快捷键&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;gg: 到页面首部&lt;/li&gt;
  &lt;li&gt;G: 到也面尾部&lt;/li&gt;
  &lt;li&gt;/: 当前页面进行搜索&lt;/li&gt;
  &lt;li&gt;n: 搜索到的下一个位置&lt;/li&gt;
  &lt;li&gt;N: 搜索到的上一个位置&lt;/li&gt;
  &lt;li&gt;C+y: 复制当前页面的URL&lt;/li&gt;
  &lt;li&gt;j k hl ：下 上 左 右移动&lt;/li&gt;
  &lt;li&gt;H L
    &lt;ul&gt;
      &lt;li&gt;H 后退一个页面&lt;/li&gt;
      &lt;li&gt;2 H 后退两个页面&lt;/li&gt;
      &lt;li&gt;L 前进一个页面&lt;/li&gt;
      &lt;li&gt;2 L 前进两个页面&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###&lt;a href=&quot;https://github.com/jinzhu/vrome/blob/master/Features.mkd&quot;&gt;&lt;strong&gt;vrome所有快捷键&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;firefox&quot;&gt;&lt;/a&gt;
##firefox浏览器&lt;/p&gt;

&lt;p&gt;&lt;em&gt;待续&lt;/em&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/11/29/bring-vim-keybindings-to-chrome.html</link>
    <guid>http://huyongde.github.io/2015/11/29/bring-vim-keybindings-to-chrome</guid>
    <pubDate>Sun, 29 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>sf 小米大数据-技术小实践</title>
    <description>&lt;p&gt;&lt;strong&gt;介绍小米大数据&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;##为么青睐hbase&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;天生为了大数据&lt;/li&gt;
  &lt;li&gt;改变schema很平滑&lt;/li&gt;
  &lt;li&gt;扩容方便&lt;/li&gt;
  &lt;li&gt;成本考虑&lt;/li&gt;
  &lt;li&gt;facebook 等公司做了很好的示范&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##小米对hbase的改进&lt;/p&gt;

&lt;p&gt;##mysql迁移hbase&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;双写&lt;/li&gt;
  &lt;li&gt;异步同步mysql老的数据到hbase&lt;/li&gt;
  &lt;li&gt;双读，并做数据校验&lt;/li&gt;
  &lt;li&gt;灰度返回hbase的结果&lt;/li&gt;
  &lt;li&gt;只写hbase&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;##&lt;a href=&quot;http://kafka.apache.org/&quot;&gt;kafka&lt;/a&gt; &amp;amp;&amp;amp; &lt;a href=&quot;http://huyongde.github.io/2015/11/28/segment-fault-big-data.html&quot;&gt;druid&lt;/a&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/11/28/segment-fault-xiaomi-big-data.html</link>
    <guid>http://huyongde.github.io/2015/11/28/segment-fault-xiaomi-big-data</guid>
    <pubDate>Sat, 28 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>SF 大数据技术分享--druid</title>
    <description>&lt;p&gt;##&lt;a href=&quot;http://druid.io/&quot;&gt;druid&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;###技术选型&lt;/p&gt;

&lt;p&gt;druid 和 spark等的比较，&lt;/p&gt;

&lt;p&gt;druid 用来进行OLAP&lt;/p&gt;

&lt;p&gt;###oneAPM 使用druid&lt;/p&gt;

&lt;p&gt;##参考&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Online_analytical_processing#Overview_of_OLAP_systems&quot;&gt;&lt;strong&gt;OLAP&lt;/strong&gt;&lt;/a&gt;  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;online analytical processing&lt;/code&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/11/28/segment-fault-big-data.html</link>
    <guid>http://huyongde.github.io/2015/11/28/segment-fault-big-data</guid>
    <pubDate>Sat, 28 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>大数据行存储还是列存储？</title>
    <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;介绍数据行存储和列存储的优缺点&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;##目录&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#简介&quot;&gt;简介&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#优缺点&quot;&gt;优缺点&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#参考&quot;&gt;参考&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id=&quot;简介&quot;&gt;&lt;/a&gt;
##简介&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;面向行&lt;/strong&gt;的数据存储架构更适用于&lt;a href=&quot;https://en.wikipedia.org/wiki/Online_transaction_processing&quot;&gt;OLTP&lt;/a&gt;-频繁交互事务的场景;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;面向列&lt;/strong&gt;的数据存储架构更适用于&lt;a href=&quot;https://en.wikipedia.org/wiki/Online_analytical_processing#Overview_of_OLAP_systems&quot;&gt;OLAP&lt;/a&gt;-(如数据仓库)这样在海量数据（(可能达到 terabyte规模)）中进行有限复杂查询的场景。&lt;/p&gt;

&lt;p&gt;###&lt;a href=&quot;http://blog.csdn.net/zhangzheng0413/article/details/8271322/&quot;&gt;OLTP和OLAP介绍&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;数据处理大致可以分成两大类：联机事务处理OLTP（on-line transaction processing）、联机分析处理OLAP（On-Line Analytical Processing）。&lt;/p&gt;

&lt;p&gt;OLTP是传统的关系型数据库的主要应用，主要是基本的、日常的事务处理，例如银行交易。&lt;/p&gt;

&lt;p&gt;OLAP是数据仓库系统的主要应用，支持复杂的分析操作，侧重决策支持，并且提供直观易懂的查询结果。&lt;/p&gt;

&lt;p&gt;OLTP 系统强调数据库内存效率，强调内存各种指标的命令率，强调绑定变量，强调并发操作；&lt;/p&gt;

&lt;p&gt;OLAP 系统则强调数据分析，强调SQL执行市场，强调磁盘I/O，强调分区等。&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;优缺点&quot;&gt;&lt;/a&gt;
##行存储，列存储优缺点&lt;/p&gt;

&lt;p&gt;###数据写入&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;**行存储**的写入是一次完成。如果这种写入建立在操作系统的文件系统上，可以保证写入过程的成功或者失败，因此数据的完整性可以确定。
**列存储**由于需要把一行记录拆分成单列保存，写入次数明显比行存储多，再加上磁头需要在盘片上移动和定位花费的时间，实际时间消耗会更大。
**所以，行存储在写入上占有很大的优势。**
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;###数据修改&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;数据修改,实际也是一次写入过程。不同的是，数据修改是对磁盘上的记录做删除标记。
**行存储**是在指定位置写入一次，
**列存储**是将磁盘定位到多个列上分别写入，这个过程仍是行存储的列数倍。
**所以，数据修改也是以行存储占优。**

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;###数据读取&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;数据读取时，
**行存储**通常将一行数据完全读出，如果只需要其中几列数据的情况，就会存在冗余列，
出于缩短处理时间的考量，消除冗余列的过程通常是在内存中进行的。
**列存储**每次读取的数据是集合的一段或者全部，如果读取多列时，就需要移动磁头，再次定位到下一列的位置继续读取。
**所以，数据读取列存储占优。**

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;###数据分布&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;对于数据分布，
**列存储**的每一列数据类型是同质的，不存在二义性问题。
比如说某列数据类型为整型（int），那么它的数据集合一定是整型数据, 这种情况使数据解析变得十分容易。
**行存储**则要复杂得多，因为在一行记录中保存了多种类型的数据，数据解析需要在多种数据类型之间频繁转换，
这个操作很消耗CPU，增加了解析的时间。
**所以，列存储的解析过程更有利于分析大数据。**
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a id=&quot;参考&quot;&gt;&lt;/a&gt;
##参考&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.infoq.com/cn/articles/bigdata-store-choose&quot;&gt;大数据存储选择-行存储还是列存储&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.douapp.com/post/525203&quot;&gt;行存储和列存储的比较&lt;/a&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/11/28/raw-or-column-store-big-data.html</link>
    <guid>http://huyongde.github.io/2015/11/28/raw-or-column-store-big-data</guid>
    <pubDate>Sat, 28 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>linux 设置输出内容的颜色</title>
    <description>&lt;p&gt;##&lt;strong&gt;目录&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#例子&quot;&gt;例子&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#my&quot;&gt;自己的使用&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#参考&quot;&gt;参考&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id=&quot;例子&quot;&gt;&lt;/a&gt;
先看下一个输出绿色字体的例子&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo &quot;colored:\e[32m\e[1mhello world\e[0m&quot;;echo &quot;end_color&quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;输出结果如下:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/color.png&quot; alt=&quot;例子&quot; /&gt;&lt;/p&gt;

&lt;p&gt;其中，&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\e[32m\e[1m&lt;/code&gt; 用来设置输出字体的颜色&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\e[0m&lt;/code&gt; 清楚开始的设置，否则之后所有的输出都是设置的字体颜色&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;my&quot;&gt;&lt;/a&gt;
##自己的使用&lt;/p&gt;

&lt;p&gt;脚本代码如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/bin/zsh
set_color=&quot;\e[32m\e[1m&quot;
clear_color=&quot;\e[0m&quot;
git add . &amp;amp;&amp;amp;  echo -e &quot;$set_color git add .     done&quot;
echo -e &quot;$clear_color&quot;
git commit -m &quot;$1&quot; &amp;amp;&amp;amp; echo &quot;$set_color git commit -m \&quot;$1\&quot;  done&quot;
echo -e &quot;$clear_color&quot;
git push origin master &amp;amp;&amp;amp; echo &quot;$set_color git push origin master done&quot;
echo -e &quot;$clear_color&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;脚本是用来提交并push本地修改代码到github主干的,并把&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add, commit push &lt;/code&gt;三步的执行结果高亮打出来，&lt;/p&gt;

&lt;p&gt;脚本运行的效果如下:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/add_commit_push_res.png&quot; alt=&quot;res&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;参考&quot;&gt;&lt;/a&gt;
##参考&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://basiccoder.com/output-colorful-words-in-terminal.html&quot;&gt;linux终端中输出彩色字体&lt;/a&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/11/27/linux-shell-color-echo.html</link>
    <guid>http://huyongde.github.io/2015/11/27/linux-shell-color-echo</guid>
    <pubDate>Fri, 27 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>tcpdump tutorial - sniffing and analysing packets from commandline</title>
    <description>&lt;p&gt;##&lt;a href=&quot;http://www.tcpdump.org/&quot;&gt;tcpdump&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;###&lt;strong&gt;目录&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;strong&gt;参考&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;####tcpdump -D&lt;/p&gt;

&lt;p&gt;D 选项option(开关switch)显示机器所有的网络接口,输出示例如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo tcpdump -D
1.en0
2.awdl0
3.bridge0
4.ppp0
5.en1
6.en2
7.p2p0
8.lo0 [Loopback]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;####tcpdump -n -vv -e -A -i&lt;/p&gt;

&lt;p&gt;n 显示ip地址，而不是显示主机名或域名&lt;/p&gt;

&lt;p&gt;-vv 显示详细信息，包括ttl，tcp flags, 数据包长度等信息&lt;/p&gt;

&lt;p&gt;-e 显示链路层头信息，包括源物理地址，目的物理地址等&lt;/p&gt;

&lt;p&gt;-A 以ascii 码显示包得内容信息&lt;/p&gt;

&lt;p&gt;-i 指定-D选项列出来的某个网络接口， -i 1 等价于-i en0&lt;/p&gt;

&lt;p&gt;tcpdump -n -vv -e -A -i 的输出如下:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;i19:54:24.717900 ac:bc:32:83:47:71 &amp;gt; a4:93:4c:76:18:4d, ethertype IPv4 (0x0800), length 46: (tos 0x0, ttl 255, id 18849, offset 0, flags [none], proto GRE (47), length 32)
    172.22.156.47 &amp;gt; 104.238.157.0: GREv1, Flags [key present, ack present], call 6656, ack 7460, no-payload, proto PPP (0x880b), length 12
E.. I..../#..../h... ..........$
19:54:24.787462 ac:bc:32:83:47:71 &amp;gt; a4:93:4c:76:18:4d, ethertype IPv4 (0x0800), length 156: (tos 0x0, ttl 255, id 42803, offset 0, flags [none], proto GRE (47), length 142)
    172.22.156.47 &amp;gt; 104.238.157.0: GREv1, Flags [key present, sequence# present, ack present], call 6656, seq 8011, ack 7460, proto PPP (0x880b), length 122
    Compressed (0x00fd), length 106: compressed PPP data
E....3.../...../h...0....j.....K...$..=o.\...\q..Oj.....b@......e_2D.?.........x1kvF
].=..r.... Y......C...D.....I.y..N?^...........-6vQ&amp;lt;b\...
19:54:24.860033 ac:bc:32:83:47:71 &amp;gt; a4:93:4c:76:18:4d, ethertype IPv4 (0x0800), length 120: (tos 0x0, ttl 127, id 37743, offset 0, flags [none], proto UDP (17), length 106)
    172.22.156.47.52693 &amp;gt; 112.80.248.135.8829: UDP, length 78
E..j.o........./pP....  K..B.A.&amp;gt;...... r.Ar..e-g..3..bZ
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;####tcpdump -w filename.pcap&lt;/p&gt;

&lt;p&gt;把抓到的包信息存储到filename.pcap文件中， 可以用&lt;a href=&quot;https://www.wireshark.org/&quot;&gt;wireshark&lt;/a&gt;分析&lt;/p&gt;

&lt;p&gt;####其他选项开关介绍&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-C filesize&lt;/strong&gt; : 当用-w filename 把抓到的数据包写到filename文件时，检查文件大小，当文件大小达到filesize，新建文件filename1继续写,直到tcpdump收到结束命令&lt;/p&gt;

&lt;p&gt;示例: tcpdump -vvv -C 1 -w filename&lt;/p&gt;

&lt;p&gt;运行一段时间后，当前文件夹下生成如下文件列表：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ls -lht
total 22352
-rw-r--r--  1 root  staff   396K 11 27 21:25 filename11
-rw-r--r--  1 root  staff   977K 11 27 21:25 filename10
-rw-r--r--  1 root  staff   977K 11 27 21:25 filename9
-rw-r--r--  1 root  staff   977K 11 27 21:25 filename7
-rw-r--r--  1 root  staff   977K 11 27 21:25 filename8
-rw-r--r--  1 root  staff   977K 11 27 21:25 filename6
-rw-r--r--  1 root  staff   977K 11 27 21:25 filename5
-rw-r--r--  1 root  staff   977K 11 27 21:25 filename2
-rw-r--r--  1 root  staff   977K 11 27 21:25 filename3
-rw-r--r--  1 root  staff   978K 11 27 21:25 filename4
-rw-r--r--  1 root  staff   978K 11 27 21:25 filename1
-rw-r--r--  1 root  staff   977K 11 27 21:25 filename
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a id=&quot;参考&quot;&gt;&lt;/a&gt;
##参考&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.binarytides.com/tcpdump-tutorial-sniffing-analysing-packets/&quot;&gt;tcpdump tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.tcpdump.org/tcpdump_man.html&quot;&gt;man tcpdump&lt;/a&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2015/11/26/linux-tcpdump.html</link>
    <guid>http://huyongde.github.io/2015/11/26/linux-tcpdump</guid>
    <pubDate>Thu, 26 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>linux network monitor commands</title>
    <description>&lt;p&gt;参考原文 &lt;a href=&quot;http://www.binarytides.com/linux-commands-monitor-network/&quot;&gt;&lt;strong&gt;18 commands to monitor network bandwidth on Linux server&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2015/11/26/linux-network-monitor-cmds.html</link>
    <guid>http://huyongde.github.io/2015/11/26/linux-network-monitor-cmds</guid>
    <pubDate>Thu, 26 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>整合disqus和jekyll，打造一个支持评论的blog</title>
    <description>&lt;p&gt;##目录&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#简介&quot;&gt;简介&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#教程&quot;&gt;教程&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#总结&quot;&gt;总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id=&quot;简介&quot;&gt;&lt;/a&gt;
##一、&lt;a href=&quot;https://disqus.com/&quot;&gt;disqus&lt;/a&gt; 简介&lt;/p&gt;

&lt;p&gt;Millions of people are talking about what they love on Disqus.&lt;/p&gt;

&lt;p&gt;(很多人都在disqus上问题)&lt;/p&gt;

&lt;p&gt;Everything from breaking news to science fiction.&lt;/p&gt;

&lt;p&gt;(自己领会这句话)&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;教程&quot;&gt;&lt;/a&gt;
##二、主要参考教程&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.perfectlyrandom.org/2014/06/29/adding-disqus-to-your-jekyll-powered-github-pages/&quot;&gt;&lt;strong&gt;adding disqus to jekyll&lt;/strong&gt;&lt;/a&gt;这个大概介绍了怎么添加&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disqus&lt;/code&gt;到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://help.disqus.com/customer/portal/articles/472007-i-m-receiving-the-message-%22we-were-unable-to-load-disqus-%22&quot;&gt;&lt;strong&gt;We were unable to load Disqus&lt;/strong&gt;&lt;/a&gt;  里面介绍了，那些原因会导致添加&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disqus&lt;/code&gt;失败，&lt;/p&gt;

&lt;p&gt;我是因为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this.page.url&lt;/code&gt;设置导致失败的，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this.page.url=window.location.href&lt;/code&gt;之后就OK了。&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://help.disqus.com/customer/portal/articles/1261429&quot;&gt;&lt;strong&gt;trust domain&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trust domain&lt;/code&gt; 主要介绍如何把自己的github pages网址，设置到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disqus&lt;/code&gt;信任的域名列表中，&lt;/p&gt;

&lt;p&gt;不设置的话 会遇到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;We were unable to load Disqus&lt;/code&gt; 错误。&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://help.disqus.com/customer/portal/articles/472098-javascript-configuration-variables&quot;&gt;&lt;strong&gt;disqus configuration variables&lt;/strong&gt;&lt;/a&gt; 介绍如何设置相关的变量值，比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this.page.url&lt;/code&gt;等。&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;总结&quot;&gt;&lt;/a&gt;
##三、总结&lt;/p&gt;

&lt;p&gt;&lt;em&gt;一定要认真阅读教程，按照理解教程的每一步。&lt;/em&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2015/11/26/add-disqus-to-jekyll-for-comments.html</link>
    <guid>http://huyongde.github.io/2015/11/26/add-disqus-to-jekyll-for-comments</guid>
    <pubDate>Thu, 26 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>为什么~号代表home目录</title>
    <description>&lt;p&gt;在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unix&lt;/code&gt;类的系统（包括：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BSD&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GUN/LIUNX&lt;/code&gt; 以及 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mac OS X&lt;/code&gt;)中，波浪号(tilde)代表当前用户的home目录.&lt;/p&gt;

&lt;p&gt;如果系统当前的登录用户是netkong,则 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd ~&lt;/code&gt; 、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd /home/netkong&lt;/code&gt; 以及 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd $HOME&lt;/code&gt;是等价的，&lt;/p&gt;

&lt;p&gt;&lt;em&gt;波浪号代表用户home目录&lt;/em&gt; ，是因为20世纪70年代的一款键盘上， 波浪号(tilde)和home(移动光标到最左边) 在同一个键，&lt;/p&gt;

&lt;p&gt;后来大家就都用波浪号(tilde)当做用户home目录&lt;/p&gt;

&lt;h2 id=&quot;当年键盘的靓图如下&quot;&gt;当年键盘的靓图如下&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/image/tilde.jpg&quot; alt=&quot;70s键盘&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;文章翻译自&quot;&gt;文章翻译自&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://unix.stackexchange.com/questions/34196/why-was-chosen-to-represent-the-home-directory&quot;&gt;&lt;strong&gt;why tilde was chosen to represent-the-home-directory&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2015/11/25/why-tilde-represents-home-directory.html</link>
    <guid>http://huyongde.github.io/2015/11/25/why-tilde-represents-home-directory</guid>
    <pubDate>Wed, 25 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>TLS 学习</title>
    <description>&lt;p&gt;##目录&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#协议&quot;&gt;相关联的协议&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ciphersuite&quot;&gt;tls密码套件&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#协议分层&quot;&gt;协议分层&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#record&quot;&gt;record协议&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#handshake&quot;&gt;handshake协议&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#参考&quot;&gt;参考&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id=&quot;协议&quot;&gt;&lt;/a&gt;
##相关联的协议
###两个主要的协议&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;做对称加密传输的record协议；
做秘钥认证协商的handshake协议；
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;###三个辅助的协议&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;changecipher spec 协议:the change cipher spec protocol,
用来通知对端从handshake切换到record协议(有点冗余，在TLS1.3里面已经被删掉了)
alert协议:the alert protocol, 用来通知各种返回码，
application data 协议: the application data protocol，
就是把http，smtp等的数据流传入record层做处理并传输。

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;###五协议的关系&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;handshake protocol,
alert protocol,
changeCipherSpec protocol,
application data protocol都封装在record protocol的包里，
然后在tcp or udp上传输
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;a id=&quot;ciphersuite&quot;&gt;&lt;/a&gt;
##tls密码套件(ciphersuite)&lt;/p&gt;

&lt;p&gt;tls大致有三个组件构成，包括:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;对称加密传输组件&lt;/li&gt;
  &lt;li&gt;认证秘钥协商组件&lt;/li&gt;
  &lt;li&gt;秘钥扩展组件&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这三个组件又可以拆为5类算法,5类算法组合在一起，称为一个密码套件(ciphersuite)
5类算法包括:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;authentication(认证算法）&lt;/li&gt;
  &lt;li&gt;encryption(加密算法)&lt;/li&gt;
  &lt;li&gt;message authentication message(消息认证码算法简称MAC)&lt;/li&gt;
  &lt;li&gt;key exchange(秘钥交换算法，简称kx)&lt;/li&gt;
  &lt;li&gt;key derivation function(秘钥衍生算法)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl ciphers -V | column -t&lt;/code&gt; 可以查看服务器支持的密码套件，本机的执行结果是:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0xC0,0x30  -  ECDHE-RSA-AES256-GCM-SHA384    TLSv1.2  Kx=ECDH        Au=RSA    Enc=AESGCM(256)    Mac=AEAD
0xC0,0x2C  -  ECDHE-ECDSA-AES256-GCM-SHA384  TLSv1.2  Kx=ECDH        Au=ECDSA  Enc=AESGCM(256)    Mac=AEAD
0xC0,0x28  -  ECDHE-RSA-AES256-SHA384        TLSv1.2  Kx=ECDH        Au=RSA    Enc=AES(256)       Mac=SHA384
0xC0,0x24  -  ECDHE-ECDSA-AES256-SHA384      TLSv1.2  Kx=ECDH        Au=ECDSA  Enc=AES(256)       Mac=SHA384
0xC0,0x14  -  ECDHE-RSA-AES256-SHA           SSLv3    Kx=ECDH        Au=RSA    Enc=AES(256)       Mac=SHA1
0xC0,0x0A  -  ECDHE-ECDSA-AES256-SHA         SSLv3    Kx=ECDH        Au=ECDSA  Enc=AES(256)       Mac=SHA1
0xC0,0x22  -  SRP-DSS-AES-256-CBC-SHA        SSLv3    Kx=SRP         Au=DSS    Enc=AES(256)       Mac=SHA1
0xC0,0x21  -  SRP-RSA-AES-256-CBC-SHA        SSLv3    Kx=SRP         Au=RSA    Enc=AES(256)       Mac=SHA1
0x00,0xA3  -  DHE-DSS-AES256-GCM-SHA384      TLSv1.2  Kx=DH          Au=DSS    Enc=AESGCM(256)    Mac=AEAD
0x00,0x9F  -  DHE-RSA-AES256-GCM-SHA384      TLSv1.2  Kx=DH          Au=RSA    Enc=AESGCM(256)    Mac=AEAD
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中， &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xC0,0x2C  -  ECDHE-ECDSA-AES256-GCM-SHA384  TLSv1.2  Kx=ECDH        Au=ECDSA  Enc=AESGCM(256)    Mac=AEAD&lt;/code&gt;解释为:&lt;/p&gt;

&lt;p&gt;名称为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ECHE-ECDSA-SES256-GCM-SHA384&lt;/code&gt;的密码套件（ciphersuite) 应用于tlsv1.2版本，&lt;/p&gt;

&lt;p&gt;使用ECDH做密钥交换算法，使用ECDSA做验证算法&lt;/p&gt;

&lt;p&gt;使用AESGCM(256)做加密算法， 使用AEAD做消息认证码算法（MAC)&lt;/p&gt;

&lt;p&gt;使用SHA384做伪随机数算法( pseudo random function简称prf),扩展密钥为数据块，使密钥更安全&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;协议分层&quot;&gt;&lt;/a&gt;
##协议分层&lt;/p&gt;

&lt;p&gt;tls是用来加密传输的，所以最终的目的是实现一个对称加密的组件进行加密传输。为了生成对称加密的密钥,&lt;/p&gt;

&lt;p&gt;需要有个认证密钥协商的过程，因此tls分为：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;认证密钥协商的handshake协议，handshake protocol&lt;/li&gt;
  &lt;li&gt;对称加密传输的record协议，record protocol&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这样就构成了tls&lt;strong&gt;认证密钥协商&lt;/strong&gt; 和 &lt;strong&gt;对称加密传输&lt;/strong&gt;的结构。&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;record&quot;&gt;&lt;/a&gt;
##record协议&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;handshake&quot;&gt;&lt;/a&gt;  &lt;br /&gt;
##handshake协议&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;参考&quot;&gt;&lt;/a&gt;
##参考&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://blog.helong.info/blog/2015/09/06/tls-protocol-analysis-and-crypto-protocol-design/&quot;&gt;&lt;strong&gt;密码学和TLS&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://kb.cnblogs.com/page/197396/&quot;&gt;&lt;strong&gt;ssl和tls的区别&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://segmentfault.com/a/1190000002963044&quot;&gt;&lt;strong&gt;tls协议实例分析&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;rfc&quot;&gt;&lt;/a&gt;
##相关RFC&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.ietf.org/rfc/rfc2246.txt&quot;&gt;The TLS Protocol Version 1.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;本文档specify (详细说明了) 1.0版本的TLS协议。 TLS协议提供了网络上私密&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;privacy&lt;/code&gt;的会话功能。
本协议允许C/S 两端基于防止窃听&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eavesdrop&lt;/code&gt;、串改&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tamper&lt;/code&gt;、伪造&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forgery&lt;/code&gt;的方式进行会话。&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.rfc-editor.org/rfc/rfc2818.txt&quot;&gt;HTTP Over TLS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;本文档描述了如何使用tls协议来保证http连接的安全性。&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.rfc-editor.org/rfc/rfc3749.txt&quot;&gt;Transport Layer Security Protocol Compression Methods&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;本文档介绍了tls的几种压缩方式&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.rfc-editor.org/rfc/rfc5246.txt&quot;&gt;The Transport Layer Security (TLS) Protocol Version 1.2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;本文档介绍了1.2版本的tls&lt;/em&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/11/25/tls.html</link>
    <guid>http://huyongde.github.io/2015/11/25/tls</guid>
    <pubDate>Wed, 25 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>linux 命令学习汇总</title>
    <description>&lt;p&gt;##目录&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#killall&quot;&gt;killall&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#lsof&quot;&gt;lsof&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#netstat&quot;&gt;netstat&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#plan&quot;&gt;学习计划&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;http://linux.die.net/&quot;&gt;&lt;strong&gt;linux man&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;killall&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;killall&quot;&gt;killall&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;killall(kill processes by nane)&lt;/code&gt; 表示通过进程名字&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kill&lt;/code&gt;进程，可以一次&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kill&lt;/code&gt;多个进程&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kill -9 pid&lt;/code&gt; 基本可以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kill&lt;/code&gt;掉所有的进程，除了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init&lt;/code&gt;进程。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;killall -9 nginx&lt;/code&gt; 可以杀掉所有通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx&lt;/code&gt;命令启动的进程&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;lsof&quot;&gt;&lt;/a&gt;
##lsof&lt;/p&gt;

&lt;p&gt;###lsof简介
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lsof&lt;/code&gt; 是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list open files&lt;/code&gt;的缩写，可以列出当前系统所有打开的文件。Linux环境下所有的事物都是以文件形式存在的。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lsof&lt;/code&gt; 通常在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/sbin/&lt;/code&gt;目录下，所以执行时，需要有相应的权限 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/sbin/lsof&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;##lsof输出结果介绍&lt;/p&gt;

&lt;p&gt;lsof输出各列信息的意义如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;COMMAND：进程的名称
PID：进程标识符
USER：进程所有者
FD：文件描述符，应用程序通过文件描述符识别该文件。如cwd、txt等 TYPE：文件类型，如DIR、REG等
DEVICE：指定磁盘的名称
SIZE：文件的大小
NODE：索引节点（文件在磁盘上的标识）
NAME：打开文件的确切名称
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;###lsof常用参数&lt;/p&gt;

&lt;p&gt;常用参数和例子&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lsof abc.txt 显示开启文件abc.txt的进程
lsof -c abc 显示abc进程现在打开的文件
lsof -c -p 1234 列出进程号为1234的进程所打开的文件
lsof -g gid 显示归属gid的进程情况
lsof +d /usr/local/ 显示目录下被进程开启的文件
lsof +D /usr/local/ 同上，但是会搜索目录下的目录，时间较长
lsof -d 4 显示使用fd为4的进程
lsof -i 显示所有打开的端口 
lsof -i:6000 显示端口号是6000的进程
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;a id=&quot;netstat&quot;&gt;&lt;/a&gt;
##netstat&lt;/p&gt;

&lt;p&gt;参考&lt;a href=&quot;http://www.binarytides.com/linux-netstat-command-examples/&quot;&gt;netstat commands samples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;###&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;netstat -alntp&lt;/code&gt; 其中&lt;/p&gt;

&lt;p&gt;a是显示所有的连接，&lt;/p&gt;

&lt;p&gt;l是显示监听的连接,&lt;/p&gt;

&lt;p&gt;n是显示ip，不显示主机名&lt;/p&gt;

&lt;p&gt;p是显示连接相关的进程&lt;/p&gt;

&lt;p&gt;###&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;netstat -nr&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;ip形式显示本机的路由表&lt;/p&gt;

&lt;p&gt;n是显示ip不显示主机名&lt;/p&gt;

&lt;p&gt;r是route路由表&lt;/p&gt;

&lt;p&gt;###&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;netstat -i&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;显示网络接口（network interfaces)&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;plan&quot;&gt;&lt;/a&gt;
##准备学习的命令 ltrace strace&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/11/25/linux-cmds.html</link>
    <guid>http://huyongde.github.io/2015/11/25/linux-cmds</guid>
    <pubDate>Wed, 25 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>翻墙看世界</title>
    <description>&lt;p&gt;##翻墙看世界(google ……)&lt;/p&gt;

&lt;p&gt;mac系统奥，&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;vpn推荐 jsqgreen&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;####&lt;a href=&quot;http://gjsq.me/12324854&quot;&gt;jsqgreen官网注册地址&lt;/a&gt;
&lt;a href=&quot;http://gjsq.me/12324854&quot;&gt;&lt;img style=&quot;border: 0px&quot; src=&quot;/image/jsqgreen.gif&quot; /&gt;&amp;lt;/img&amp;gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;每个系统的安装使用，官网都有相关的教程，自己用了一阵，免费试用的线路足够用了。&lt;/p&gt;

&lt;p&gt;jsqgreen 的缺点是，免费线路的vpn地址可能经常变，所以链接不上后，需要去官网线路列表看看，是否vpn的地址已经更新了。&lt;/p&gt;

&lt;p&gt;设置访问国内网站不走vpn,的设置&lt;/p&gt;

&lt;p&gt;推荐&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chnroutes&lt;/code&gt;,&lt;a href=&quot;https://github.com/huyongde/chnroutes&quot;&gt;chnroutes github&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;配置完了，vpn 的ip_up 和ip_down之后能访问国内网站不走vpn了，但是还是访问不了

公司的内网。

有空再折腾下。

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;##相关名词解释&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vpn&lt;/code&gt; : &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virtual priavate network&lt;/code&gt;  虚拟专用网络&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vps&lt;/code&gt; : &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virtual private servers &lt;/code&gt;   虚拟专用服务器&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/11/24/vpn-goout-see-world.html</link>
    <guid>http://huyongde.github.io/2015/11/24/vpn-goout-see-world</guid>
    <pubDate>Tue, 24 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>c++获得文件大小</title>
    <description>&lt;h1 id=&quot;c获得文件大小的几种方式&quot;&gt;c++获得文件大小的几种方式&lt;/h1&gt;

&lt;p&gt;##第一种&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt;&lt;span class=&quot;cpf&quot;&gt;&amp;lt;io.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt;&lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filelength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;file size&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;##第二种&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt;&lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt;&lt;span class=&quot;cpf&quot;&gt;&amp;lt;windows.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//创建文件句柄&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;HANDLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fhandle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CreateFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OPEN_EXISTING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;DWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GetFileSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fhandle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;filesize&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;##第三种&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt;&lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fopen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;rb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fseek&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SEEK_END&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ftell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fclose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;filesize&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
    <link>http://huyongde.github.io/2015/11/24/cplusplus-getfilesize.html</link>
    <guid>http://huyongde.github.io/2015/11/24/cplusplus-getfilesize</guid>
    <pubDate>Tue, 24 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>markdown 学习</title>
    <description>&lt;h1 id=&quot;主题&quot;&gt;主题&lt;/h1&gt;

&lt;h1&gt; markdown 学习 &lt;/h1&gt;

&lt;hr /&gt;

&lt;p&gt;TOC&lt;/p&gt;

&lt;p&gt;##Table of Content&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#主题&quot;&gt;主题&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#参考&quot;&gt;参考&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##段落
通过空行来形成不同的段落&lt;/p&gt;

&lt;p&gt;##标题&lt;/p&gt;

&lt;p&gt;###atx标题
# The largest heading (an &amp;lt;h1&amp;gt; tag)&lt;/p&gt;

&lt;p&gt;## The second largest heading (an &amp;lt;h2&amp;gt; tag)&lt;/p&gt;

&lt;p&gt;…..&lt;/p&gt;

&lt;p&gt;###### The 6th largest heading (an &amp;lt;h6&amp;gt; tag)&lt;/p&gt;

&lt;p&gt;###setext标题&lt;/p&gt;

&lt;p&gt;=== 一级标题&lt;/p&gt;

&lt;p&gt;---二级标题&lt;/p&gt;

&lt;p&gt;##引用(blockquotes)
文字前面加上&amp;gt;，&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;这里是个引用&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;##文字加粗&amp;amp;&amp;amp;斜体
&lt;em&gt;这里是斜体&lt;/em&gt; (文字前后都加上*,可以使文字变成斜体）&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;这里是粗体&lt;/strong&gt; （文字前后都加2个*,可以变为粗体）&lt;/p&gt;

&lt;p&gt;##列表
###无序列表
文字前面机上*或者-来表示无须列表&lt;/p&gt;

&lt;p&gt;* item&lt;/p&gt;

&lt;p&gt;* item&lt;/p&gt;

&lt;p&gt;* item&lt;/p&gt;

&lt;p&gt;效果如下:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;item&lt;/li&gt;
  &lt;li&gt;item&lt;/li&gt;
  &lt;li&gt;item&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;###有序列表
文字前面加上数字表示有序列表&lt;/p&gt;

&lt;p&gt;\1.item1&lt;/p&gt;

&lt;p&gt;\2.item2&lt;/p&gt;

&lt;p&gt;效果如下:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;item1&lt;/li&gt;
  &lt;li&gt;item2&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;##表格&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;表头1&lt;/th&gt;
      &lt;th&gt;表头2&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;xxxxx&lt;/td&gt;
      &lt;td&gt;yyyyy&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;##链接图片
!&lt;a href=&quot;&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/IMG_1979.JPG&quot; alt=&quot;网球&quot; /&gt;&lt;/p&gt;

&lt;p&gt;##代码块
行内代码用`` 把代码包起来&lt;/p&gt;

&lt;p&gt;代码块用```代码```&lt;/p&gt;

&lt;p&gt;c的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf()&lt;/code&gt;函数&lt;/p&gt;

&lt;p&gt;下面是一段代码&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;local a = xxxx
ngx.say(a)
ngx.print(a)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;##参考&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://help.github.com/articles/markdown-basics/&quot;&gt;&lt;em&gt;markdown basic&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://guides.github.com/features/mastering-markdown/&quot;&gt;&lt;em&gt;markdown master&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.jianshu.com/p/q81RER&quot;&gt;markdown 入门2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://ibruce.info/2013/11/26/markdown/&quot;&gt;&lt;strong&gt;markdown 入门精选&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://wowubuntu.com/markdown/&quot;&gt;&lt;strong&gt;markdown 简体中文教程&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://25.io/mou/&quot;&gt;&lt;strong&gt;&lt;em&gt;markdown 编辑器 mou&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://uliweb.clkg.org/wiki/Help/MarkdownSyntax&quot;&gt;markdown 设置图片大小&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;23 Nov 2015&lt;/em&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2015/11/23/markdown-learn.html</link>
    <guid>http://huyongde.github.io/2015/11/23/markdown-learn</guid>
    <pubDate>Mon, 23 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>Learn Ngx_openresty</title>
    <description>&lt;h1 id=&quot;name&quot;&gt;Name&lt;/h1&gt;

&lt;p&gt;ngx_openresty - Turning Nginx into a full-fledged Web App Server&lt;/p&gt;

&lt;h1 id=&quot;table-of-contents&quot;&gt;Table of Contents&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#name&quot;&gt;Name&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#description&quot;&gt;Description&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#for-users&quot;&gt;For Users&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#for-bundle-maintainers&quot;&gt;For Bundle Maintainers&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#mailing-list&quot;&gt;Mailing List&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#report-bugs&quot;&gt;Report Bugs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#copyright--license&quot;&gt;Copyright &amp;amp; License&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;description&quot;&gt;Description&lt;/h1&gt;

&lt;p&gt;ngx_openresty is a full-fledged web application server by bundling the standard nginx core,
lots of 3rd-party nginx modules, as well as most of their external dependencies.&lt;/p&gt;

&lt;p&gt;This bundle is maintained Yichun Zhang (agentzh).&lt;/p&gt;

&lt;p&gt;Because most of the nginx modules are developed by the bundle maintainers, it can ensure
that all these modules are played well together.&lt;/p&gt;

&lt;p&gt;The bundled software components are copyrighted by the respective copyright holders.&lt;/p&gt;

&lt;p&gt;The homepage for this project is http://openresty.org.&lt;/p&gt;

&lt;h2 id=&quot;for-users&quot;&gt;For Users&lt;/h2&gt;

&lt;p&gt;Visit http://openresty.org/#Download to download the latest bundle tarball, and
follow the installation instructions in the page http://openresty.org/#Installation.&lt;/p&gt;

&lt;h2 id=&quot;for-bundle-maintainers&quot;&gt;For Bundle Maintainers&lt;/h2&gt;

&lt;p&gt;The bundle’s source is at the following git repository:&lt;/p&gt;

&lt;p&gt;https://github.com/openresty/ngx_openresty&lt;/p&gt;

&lt;p&gt;To reproduce the bundle tarball, just do&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;at the top of the bundle source tree.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;#table-of-contents&quot;&gt;Back to TOC&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;mailing-list&quot;&gt;Mailing List&lt;/h1&gt;

&lt;p&gt;You’re very welcome to join the English OpenResty mailing list hosted on Google Groups:&lt;/p&gt;

&lt;p&gt;https://groups.google.com/group/openresty-en&lt;/p&gt;

&lt;p&gt;The Chinese mailing list is here:&lt;/p&gt;

&lt;p&gt;https://groups.google.com/group/openresty&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;#table-of-contents&quot;&gt;Back to TOC&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;report-bugs&quot;&gt;Report Bugs&lt;/h1&gt;

&lt;p&gt;You’re very welcome to report issues on GitHub:&lt;/p&gt;

&lt;p&gt;https://github.com/agentzh/ngx_openresty/issues&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;#table-of-contents&quot;&gt;Back to TOC&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;copyright--license&quot;&gt;Copyright &amp;amp; License&lt;/h1&gt;

&lt;p&gt;The bundle itself is licensed under the 2-clause BSD license.&lt;/p&gt;

&lt;p&gt;Copyright (c) 2011-2015, Yichun “agentzh” Zhang (章亦春) &lt;a href=&quot;mailto:agentzh@gmail.com&quot;&gt;agentzh@gmail.com&lt;/a&gt;, CloudFlare Inc.&lt;/p&gt;

&lt;p&gt;This module is licensed under the terms of the BSD license.&lt;/p&gt;

&lt;p&gt;Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.&lt;/li&gt;
  &lt;li&gt;Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS
IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;#table-of-contents&quot;&gt;Back to TOC&lt;/a&gt;&lt;/p&gt;

</description>
    <link>http://huyongde.github.io/2015/11/23/learn-ngx_openresty.html</link>
    <guid>http://huyongde.github.io/2015/11/23/learn-ngx_openresty</guid>
    <pubDate>Mon, 23 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>jekyll 入门 && jekyll 搭建github page的框架</title>
    <description>&lt;p&gt;##参考&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://github.tiankonguse.com/blog/2014/11/10/jekyll-study/&quot;&gt;jekyll语法介绍&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://jobinson.ga/%E5%BB%BA%E7%AB%99%E4%B9%8B%E8%B7%AF/2014/04/27/%E4%BD%BF%E7%94%A8jekyll%E7%94%9F%E6%88%90%E9%9D%99%E6%80%81%E7%AB%99/&quot;&gt;jekyll 安装和初始化站点&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://trefoil.github.io/2013/10/05/jekyll.html&quot;&gt;jekyll 入门&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://uliweb.clkg.org/wiki/Help/MarkdownSyntax&quot;&gt;markdown 设置图片大小&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;主题&quot;&gt;主题&lt;/h1&gt;

&lt;h1&gt; jekyll 入门 &amp;amp;&amp;amp; jekyll 搭建github page的框架 &lt;/h1&gt;

&lt;hr /&gt;

&lt;p&gt;##jekyll 安装&lt;/p&gt;

&lt;p&gt;通过gem来安装，gem是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;perl&lt;/code&gt;语言各种扩展包得管理工具&lt;/p&gt;

&lt;p&gt;安装命令如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo gem install jekyll
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;##初始化站点&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mdkir jekyll_site
jekyll new jekyll_site
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;执行完 jekyll new jekyll_site&lt;/p&gt;

&lt;p&gt;执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd jekyll_site; tree&lt;/code&gt;可以看到站点的目录结构,如下:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/tree_re.png&quot; alt=&quot;jekyll站点目录&quot; /&gt;&lt;/p&gt;

&lt;p&gt;通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll server&lt;/code&gt; 就可以启动本地服务查看站点&lt;/p&gt;

&lt;p&gt;jekyll server 执行结果如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Configuration file: /Users/huyongde/tmp/jekyll_site/_config.yml
            Source: /Users/huyongde/tmp/jekyll_site
       Destination: /Users/huyongde/tmp/jekyll_site/_site
 Incremental build: disabled. Enable with --incremental
      Generating...
                    done in 0.259 seconds.
 Auto-regeneration: enabled for '/Users/huyongde/tmp/jekyll_site'
Configuration file: /Users/huyongde/tmp/jekyll_site/_config.yml
    Server address: http://127.0.0.1:4000/
  Server running... press ctrl-c to stop.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;浏览器访问&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;127.0.0.1:4000&lt;/code&gt; 就可以在本地看到jekyll生成的blog了，&lt;/p&gt;

&lt;p&gt;效果如下图&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/jekyll_server.png&quot; alt=&quot;本机blog效果图&quot; /&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;[[效果图:/image/jekyll_server.png&lt;/td&gt;
      &lt;td&gt;center&lt;/td&gt;
      &lt;td&gt;100px&lt;/td&gt;
      &lt;td&gt;100px]]&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;##博客迁移到github pages&lt;/p&gt;

&lt;p&gt;github中建立一个项目，项目名称叫 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;你的github名字.github.io&lt;/code&gt;,比如我的github账号名字是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;huyongde&lt;/code&gt;,&lt;/p&gt;

&lt;p&gt;我创建的项目名称就是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;huyongde.github.io&lt;/code&gt;, 然后把&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll new&lt;/code&gt; 出来的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll_site&lt;/code&gt;文件夹中的文件加到项目中，&lt;/p&gt;

&lt;p&gt;过会访问&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;你的github名字.github.io&lt;/code&gt;, 就可以看到你的github pages 上的blog了。&lt;/p&gt;

&lt;p&gt;下图是我的github pages效果图(改过博客主题，加了一些文章之后的)：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/huyongde_githubpages.png&quot; alt=&quot;my github page blog&quot; /&gt;&lt;/p&gt;

&lt;p&gt;##jekyll 配置&lt;/p&gt;

&lt;p&gt;###代码块的功能不能用解决办法(我这边是如下解决的，仅供参考（MAC OS))：&lt;/p&gt;

&lt;p&gt;_config.yml中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;markdown:cramdown&lt;/code&gt; 配置改成&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;markdown:rdiscount&lt;/code&gt;, 把markdown解释器改成rdiscount ,之后代码块就生效了,代码块示例：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$a = &quot;php code&quot;;
echo $a;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;下面是通过highlight高亮的代码:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;php code&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;23 Nov 2015&lt;/em&gt;&lt;/p&gt;
</description>
    <link>http://huyongde.github.io/2015/11/23/jekyll-learn.html</link>
    <guid>http://huyongde.github.io/2015/11/23/jekyll-learn</guid>
    <pubDate>Mon, 23 Nov 2015 00:00:00 +0000</pubDate>
  </item>

  <item>
    <title>c++ setw使用 以及 markdown中 highlight 加亮代码</title>
    <description>&lt;h1 id=&quot;主题&quot;&gt;主题&lt;/h1&gt;

&lt;p&gt;#c++ setw使用 以及 markdown中 highlight 加亮代码&lt;/p&gt;

&lt;p&gt;使用setw(n)设置输出的宽度，默认是右对齐，&lt;/p&gt;

&lt;p&gt;示例代码:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;std::cout &amp;lt;&amp;lt; std::setw(5) &amp;lt;&amp;lt; &quot;1&quot;    &amp;lt;&amp;lt; std::endl;
std::cout &amp;lt;&amp;lt; std::setw(5) &amp;lt;&amp;lt; &quot;10&quot;   &amp;lt;&amp;lt; std::endl;
std::cout &amp;lt;&amp;lt; std::setw(5) &amp;lt;&amp;lt; &quot;100&quot;  &amp;lt;&amp;lt; std::endl;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;通过left可以设置左对齐&lt;/p&gt;

&lt;p&gt;示例代码：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;std::cout &amp;lt;&amp;lt; std::left &amp;lt;&amp;lt; std::setw(5) &amp;lt;&amp;lt; &quot;1&quot;    &amp;lt;&amp;lt; std::endl;
std::cout &amp;lt;&amp;lt; std::left &amp;lt;&amp;lt; std::setw(5) &amp;lt;&amp;lt; &quot;10&quot;   &amp;lt;&amp;lt; std::endl;
std::cout &amp;lt;&amp;lt; std::left &amp;lt;&amp;lt; std::setw(5) &amp;lt;&amp;lt; &quot;100&quot;  &amp;lt;&amp;lt; std::endl;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如下是用highlight高亮后的代码:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10&quot;&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;100&quot;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;未用highlight高亮的python代码：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import sys
def func1():
    return 0

sys.exit(200)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;highlight高亮的python代码：&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;func1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
    <link>http://huyongde.github.io/2015/11/23/cout-setw.html</link>
    <guid>http://huyongde.github.io/2015/11/23/cout-setw</guid>
    <pubDate>Mon, 23 Nov 2015 00:00:00 +0000</pubDate>
  </item>


</channel>
</rss>
