<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Some reminiscences, some memories</title>
	<atom:link href="http://www.mikespook.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mikespook.com</link>
	<description>Just another boring day</description>
	<lastBuildDate>Fri, 17 Feb 2012 09:04:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>[翻译]go 工具</title>
		<link>http://www.mikespook.com/2012/02/%e7%bf%bb%e8%af%91go-%e5%b7%a5%e5%85%b7/</link>
		<comments>http://www.mikespook.com/2012/02/%e7%bf%bb%e8%af%91go-%e5%b7%a5%e5%85%b7/#comments</comments>
		<pubDate>Fri, 17 Feb 2012 07:57:27 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[Golang]]></category>
		<category><![CDATA[go tool]]></category>
		<category><![CDATA[golang]]></category>
		<category><![CDATA[makefile]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/?p=1225</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
go 工具来了，集大成，全整合。没了 Makefile 还真有点不习惯。此文甚好，早就想翻译了，无奈最近焦头烂额……不管怎么样，还是动手了。

原文要翻墙，访问请谨慎：The go tool

&#8212;&#8212;&#8212;&#8212;&#8212;-翻译分隔线&#8212;&#8212;&#8212;&#8212;&#8212;-

<span class="readmore"><a href="http://www.mikespook.com/2012/02/%e7%bf%bb%e8%af%91go-%e5%b7%a5%e5%85%b7/" title="[翻译]go 工具">阅读全文——共4902字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>go 工具来了，集大成，全整合。没了 Makefile 还真有点不习惯。此文甚好，早就想翻译了，无奈最近焦头烂额……不管怎么样，还是动手了。</p>
<p>原文要翻墙，访问请谨慎：<a href="http://areyoufuckingcoding.me/2012/02/14/the-go-tool/" target="_blank">The go tool</a></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;-翻译分隔线&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>线上介绍了 go 命令的最新 weekly 发布后，我决定写一些关于它的内容。我得承认，在第一次听说统一 go 工具的时候，我满是怀疑并对此非常恐惧。我担心它会像大多数其他语言特定的包管理器一样混乱。个人认为多数这种包管理器都是在重新发明轮子，并且与操作系统的包管理器发生冲突，让系统管理员生活的更加艰辛。另外，我确实喜欢 makefile，它们简单并且直接，工作得也很好。幸运的是，新的 go 工具驱散了我的恐惧！<br />
<span id="more-1225"></span></p>
<h1>拒绝重复&#8230;</h1>
<p>最近在 <a href="http://groups.google.com/group/golang-nuts/browse_thread/thread/b4bb313b64b8ca84/4bc3cda688c04b57?lnk=gst&#038;q=the+go+command#4bc3cda688c04b57" target="_blank">go nuts</a> 邮件列表上有大量的关于新的 go 工具的信息。官方的 go 文档也包含了一些关于如何使用 go 工具<a href="http://weekly.golang.org/doc/code.html" target="_blank">编写 go 代码</a>的短文。</p>
<p>无论如何，我觉得当前在这些文档中还存在一些缺漏，因此这成为了撰写关于新的 go 工具的快速指南，并对一些技巧加以演示的理由。</p>
<h1>配置的约定</h1>
<p>这是我恐惧最大的来源，多半是因为我在 Ruby on Rails 上的经历。所有熟悉 Rails 的开发者都会同意，每当你尝试做一些微小的改进，一点点小技巧，一些不遵循规则的东西，它就……</p>
<p><a href="http://www.mikespook.com/wp-content/uploads/2012/02/meme-impossibru.jpg"><img src="http://www.mikespook.com/wp-content/uploads/2012/02/meme-impossibru.jpg" alt="" title="meme-impossibru" width="420" height="315" class="alignnone size-full wp-image-1228" /></a></p>
<p>不过还是来谈谈最佳实践吧。首先，每个 go 工具只做一件事情，并且把这件事情做得很好。例如，我们有：</p>
<ul>
<li><strong><code>go build</code></strong> &#8211; 编译包，</li>
<li><strong><code>go get</code></strong> &#8211; 解析并安装依赖，</li>
<li><strong><code>go test</code></strong> &#8211; 执行测试用例和性能测试，</li>
<li><strong><code>go install</code></strong> &#8211; 安装包，</li>
<li><strong><code>go doc</code></strong> &#8211; 生成文档，</li>
<li><strong><code>go fmt</code></strong> &#8211; 格式化代码，</li>
<li><strong><code>go run</code></strong> &#8211; 构建并执行应用，</li>
<li><strong><code>go tool</code></strong> &#8211; 调用扩展工具，</li>
<li>等等……</li>
</ul>
<p>go 包<strong>没有任何的构建配置</strong>。没有 makefile，没有依赖描述等等。那么它如何工作的？所有都是从<strong>代码</strong>中获取。为了让这个魔法生效，首先有一件事情要做。需要指定 go 那些七七八八都存在哪里。环境变量 <strong>GOPATH</strong> 定义了 go 代码树的路径。例如，下面是在 ~/.bashrc 中的：</p>
<pre class="brush: bash; title: ; notranslate">
GOPATH=&quot;/home/nu7/gocode&quot;
</pre>
<p>……告诉 go 工具你的 go 代码树存放在指定的目录中。但是你可能想知道 <strong>go 代码树到底是什么</strong>？简单说，它就是<strong>所有 go 资源、包和命令存放的地方</strong>。例如：</p>
<pre class="brush: bash; title: ; notranslate">
$ ls /home/nu7/gocode/
bin   pkg   src
</pre>
<p>所有的代码会放到 src 目录。我所说的所有的代码意味着包含你的应用、包和依赖。pkg 目录包含编译和安装后的包，而 bin 存放命令。</p>
<p>GOPATH 变量的工作方式与 PATH 类似，可以随意设置若干个 go 路径。不过务必记得其中的第一个是主要路径，因此使用 go install 安装的内容将全部存放于此。</p>
<h1>解决依赖</h1>
<p>没有用来描述依赖关系的配置文件……那么高明的 go 工具是如何判断安装什么，以及从哪里下载呢！你认为在某个地方有一个仓库？不对，没有这个！Go 带来了叫做 importpath 的东西，来看看：</p>
<pre class="brush: bash; title: ; notranslate">
import &amp;quot;github.com/nu7hatch/gouuid&amp;quot;
</pre>
<p>导入路径是二合一的。它是代码仓库 URL 和包将安装的本地路径。<strong>go get</strong> 工具只需要看看导入路径就知道从哪里获得依赖，而 <strong>go build</strong> 也能知道在本地从哪里导入它们。</p>
<p>为了<strong>在系统中安装依赖</strong>，必须这样使用 go get 工具：</p>
<pre class="brush: bash; title: ; notranslate">
$ go get package-name
</pre>
<p>等等，等等……这里的 package-name 是什么？这是希望安装的依赖的包的名字。假设在 go 代码中有一个叫做 foo 的包，调用 go get foo 将会安装其所有的依赖。同样可以在包中直接运行这个工具：</p>
<pre class="brush: bash; title: ; notranslate">
$ cd ~/gocode/src/foo
$ go get .
</pre>
<p>其他所有的 go 工具都是类似的方式工作，并且可以在包中直接调用，或指定导入路径。同时也可以<strong>在一组嵌套的包上使用</strong> &#8230;（三个点）通配执行命令。如果 foo 包包含一些嵌套的包，为了一次安装所有需要的依赖，只需要执行：</p>
<pre class="brush: bash; title: ; notranslate">
$ go get ./...
</pre>
<p>如果指定的依赖已经安装在了 go 代码树中，除非明确指定，否则就<strong>不会进行更新</strong>。在执行 <strong>go get</strong> 进行依赖安装的时候，增加 <strong>-u</strong> 标识进行更新：</p>
<pre class="brush: bash; title: ; notranslate">
$ go get -u package-name
</pre>
<p>很简单，不是吗？</p>
<h1>依赖的地狱！</h1>
<p>go tool 有一个约定是我特别喜欢的，不过恐怕与此同时……go 工具通过<strong>检出代码库的 HEAD 版本</strong>来解决依赖。这强制包保持<a href="http://semver.org/" target="_blank">向下兼容</a>，并且……</p>
<p><a href="http://www.mikespook.com/wp-content/uploads/2012/02/meme-jules-1.jpg"><img src="http://www.mikespook.com/wp-content/uploads/2012/02/meme-jules-1.jpg" alt="" title="meme-jules-1" width="420" height="276" class="alignnone size-full wp-image-1233" /></a></p>
<p><strong>绿色主线政策</strong>是我在工作中一直坚持的。默认分支总是首先被检出的，因此它应当<strong>保持干净</strong>，或者至少它应当<strong>可以工作</strong>！一旦官方发布，或者已经成熟，它应当同样有<strong>向下兼容的能力</strong>——总不能在补丁或者小版本上推翻或者修改 API 吧。</p>
<p>不过我们都知道在实践的时候是怎么回事。许多人像把向下兼容当作一坨屎，或把默认分支当作游乐场，等等。对于那些人，以及所有期望同新的 go 工具和平共处的开发者，我有一些建议……</p>
<div style="background: none repeat scroll 0 0 #FFFFAA; padding: 1.5em;">
<h4 style="color: #DD2222;">在该死的程序员生涯中应当遵循的守则：</h4>
<ul>
<li><strong>保持该死的主线干净！</strong></li>
<li><strong>在该死的独立分支上进行该死的新功能的开发！</strong></li>
<li>一旦你公布了代码，并且某些人使用了它，<strong>那就 TMD 不要修改 API！</strong></li>
<li>如果想要或者必须修改 API，<strong>修改 TMD 主版本号</strong> 并且 <strong>在独立于原代码库的新的代码库上进行该死的开发！</strong>
</li>
<li>如果有必要，<strong>非常有必要</strong>使用某些特别的标签，做分支或提交作为依赖，<strong>你得 TMD 用自己 fork 出来的代码库进行 TMD 所需要的提交！</strong></li>
<li>哦，还有<strong>保持简单</strong>，狗娘养的！</li>
</ul>
</div>
<p>别让我给你读以西结书（译注：《希伯来圣经》中的一部先知书）来提醒你这些……</p>
<h1>构建和安装</h1>
<p>好，让我们回到 go 命令。<strong>go build</strong> 命令用于编译包。它仅仅编译指定包，而不会进行安装。重要的是，<strong>它要求包已经检出在本地代码树中</strong>。要安装远程包应当使用 <strong>go get</strong> 来代替：</p>
<pre class="brush: bash; title: ; notranslate">
$ go get github.com/nu7hatch/gouuid
</pre>
<p>安装本地包当然使用 go install 工具。（如果有必要的话）它首先构建包然后将其安装在 $GOPATH/pkg 或者/以及 $GOPATH/bin。</p>
<p> go 工具在<strong>构建的时候也能忽略文件</strong>，无需显式的指定额外的参数或者特别的配置。对于要忽略的文件唯一要做的，就是让其名字前有一个下划线：</p>
<pre class="brush: bash; title: ; notranslate">
$ ls
_bar.go   foo.go
$ go build .
</pre>
<p>在上面的例子中，构建时 _bar.go 将会被忽略。</p>
<p>唔，就这样吧……我想关于这些也没什么好说的了，让我们继续下面的内容。</p>
<h1>用 CGO 的 C 扩展</h1>
<p>go 通过 <a href="http://http//weekly.golang.org/cmd/cgo/" target="_blank">cgo 命令</a>获得了<strong>构建 C 扩展</strong>的良好支持。实际上，编译大多数 C 支持的应用，甚至无需了解 cgo，go build 工具足够了。</p>
<p>实话说，关于 cgo 真没什么好讲的，文档和 <a href="http://code.google.com/p/go-wiki/wiki/cgo" target="_blank">go user wiki 中的文章</a>已经涵盖了大部分内容。</p>
<p>首先要说说的是那些我确实不喜欢的东西，也就是在官方例子中展示的将 C 代码写在注释中的做法。你得知道，这些例子主要是为了减少代码的尺寸并让每个例子都在同一个文件中演示。在实际的应用中 <strong>C 代码不应当放在注释部分</strong>！go build 工具能够聪明的处理包中的 .h 和 .c 文件。</p>
<p>需要一些例子？来看一个将所有参数都打印到屏幕上的简单的 echo 命令，不过要使用来自 stdio.h 的 printf 函数。与 wiki 上所述一致，<strong>go 不允许调用变长参数的 C 函数</strong>，因此需要对 printf 函数编写一个简单的包裹。代码看起来大约是这样（同样可在 <a href="http://github.com/nu7hatch/cgoecho" target="_blank">github 上</a>浏览到）：</p>
<p>echo.h：</p>
<pre class="brush: cpp; title: ; notranslate">
#ifndef _ECHO_H_
#define _ECHO_H_

#include &lt;stdio.h&gt;

void echo(char*);

#endif /* _ECHO_H_ */
</pre>
<p>echo.c：</p>
<pre class="brush: cpp; title: ; notranslate">
#include &quot;echo.h&quot;

void echo(char* s)
{
    printf(&quot;%s\n&quot;, s);
}
</pre>
<p>echo.go：</p>
<pre class="brush: cpp; title: ; notranslate">
package main

/*
#include &lt;stdlib.h&gt;
#include &quot;echo.h&quot;
*/
import &quot;C&quot;

import (
        &quot;flag&quot;
        &quot;unsafe&quot;
        &quot;strings&quot;
)

func main() {
        flag.Parse()
        cs := C.CString(strings.Join(flag.Args(), &quot; &quot;))
        C.echo(cs)
        C.free(unsafe.Pointer(cs))
}
</pre>
<p>现在可以用 go build 工具无缝的编译所有的东西。它能识别出在包中所有的 C 文件。简单来说这就能工作了！</p>
<p><a href="http://www.mikespook.com/wp-content/uploads/2012/02/meme-notbad-1.jpg"><img src="http://www.mikespook.com/wp-content/uploads/2012/02/meme-notbad-1.jpg" alt="" title="meme-notbad-1" width="420" height="304" class="alignnone size-full wp-image-1236" /></a></p>
<h1>特定平台的构建</h1>
<p>go build 另一个很酷却又有趣的地方是处理特定平台的文件。它能通过名字来识别（必须是像 file_GOOS_GOARCH.go 或者 file_GOARCH.go ）：</p>
<pre class="brush: bash; title: ; notranslate">
foo_darwin_amd64.go
foo_386.go
foo.go
</pre>
<p>这个功能对 C 文件同样适用：</p>
<pre class="brush: bash; title: ; notranslate">
foo_amd64.c
foo_386.c
foo.h
foo.go
</pre>
<p>就像文档里说的那样，你可能永远都用不到这个功能，不过我还是像给大家展示一下 go 工具在如此简单的基础上做到了多么的灵活。</p>
<p>好，但是你们当中可能有人会问，如果要做一些棘手的事情需要特殊的编译参数或者一些配置，例如……</p>
<h1>救世主 Makefile</h1>
<p>是的，不要害怕使用 makefile！这是最简便的方法来做额外的配置，一些预请求等等。makefile 不但对于 C 扩展很有帮助，对于具有多个包的应用也同样适用（例如，在 <a href="http://github.com/webrocket/webrocket" target="_blank">webrocket</a> 中使用了一个顶级的 makefile 来让任务更加轻松）。</p>
<p>更加清楚的例子……设想一个包含了内核包和基于此的命令行工具的应用。可以套用 echo 的例子，不过更加模块化：</p>
<pre class="brush: bash; title: ; notranslate">
echo/
  pkg/
    echo/
      echo.c
      echo.h
      echo.go
  cmd/
    echo/
      echo.go
</pre>
<p>希望 pkg/echo 包提供一个可重用的 C printf 函数的包裹，它的代码看起来跟前面的例子中的一样。cmd/echo 命令是一个使用了核心包来打印到屏幕的可执行文件。cmd/echo 命令是这样：</p>
<pre class="brush: cpp; title: ; notranslate">
package main

import (
        &quot;github.com/nu7hatch/cgoecho2/pkg/echo&quot;
        &quot;flag&quot;
)

func main() {
        flag.Parse()
        echo.Echo(flag.Args()...)
}
</pre>
<p><strong>注意</strong>：对于那些不了解 slice 的人来说 &#8230; 意味着将一个 slice 映射到变长参数，就像 Ruby 中的 *args。</p>
<p>回到主题，为了让对包的工作更加简单，需要一些 Makefile。看起来大约是这样：</p>
<pre class="brush: bash; title: ; notranslate">
all: echo-pkg echo-cmd

echo-pkg:
    go build ./pkg/echo

echo-cmd:
    go build ./cmd/echo
</pre>
<p>现在就可以通过调用 make 来快速的编译包和命令两个部分，还有一个很重要的，<strong>可以使用 go 命令远程安装</strong>：</p>
<pre class="brush: bash; title: ; notranslate">
$ go get github.com/nu7hatch/cgoecho2/cmd/echo
</pre>
<p>当然这时非常简单的一个例子，完全可以使用通配来进行快速的构建，而不必这么小题大作：</p>
<pre class="brush: bash; title: ; notranslate">
$ go build ./...
</pre>
<p>但是面对更大的应用，包含许多包和/或命令就会是王道了。那时有各种理由使用 makefile、shell 脚本或者任何你喜欢的构建工具。</p>
<h1>总结</h1>
<p>我不得不明确表态，我 TMD 超级喜欢新的 go 工具！在第一次用的时候，我遇到了一大堆麻烦，不过大多数都是因为我从其他包管理工具上养成的坏习惯。哈，最近我在 go-nuts IRC 上问了许多愚蠢的问题，而我想要的答案是如此的显而易见并且简单……</p>
<p>现在回顾用过的全部工具，例如 easy_install、rubygems 或者 bundler，我对它们只有一个印象……哦，我还是不要说出来了，免得许多人恨我 <img src='http://www.mikespook.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> 。取而代之，我可以向你展示我是如何看待新的 go 工具的……</p>
<p><a href="http://www.mikespook.com/wp-content/uploads/2012/02/meme-superman-1.jpg"><img src="http://www.mikespook.com/wp-content/uploads/2012/02/meme-superman-1.jpg" alt="" title="meme-superman-1" width="400" height="300" class="alignnone size-full wp-image-1237" /></a></p>
<p>看到 Go 正在向好的方向发展，我很欣慰！今天就到这里吧，好运，Gopher 们！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2012/02/%e7%bf%bb%e8%af%91go-%e5%b7%a5%e5%85%b7/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[翻译]从 r60 到 Go 1</title>
		<link>http://www.mikespook.com/2012/02/%e7%bf%bb%e8%af%91%e4%bb%8e-r60-%e5%88%b0-go-1/</link>
		<comments>http://www.mikespook.com/2012/02/%e7%bf%bb%e8%af%91%e4%bb%8e-r60-%e5%88%b0-go-1/#comments</comments>
		<pubDate>Mon, 13 Feb 2012 04:47:59 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[Golang]]></category>
		<category><![CDATA[go1]]></category>
		<category><![CDATA[golang]]></category>
		<category><![CDATA[r60]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/?p=1222</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
Go1 发布的日子越来越近，Golang 社区就像将开了的山泉水一样，泊泊的不断传来各种关于 Go1 的声音。

这篇文章总结得比较完整，很清晰，随即翻译于此。

原文：http://gophersays.com/from-r60-to-go1/

<span class="readmore"><a href="http://www.mikespook.com/2012/02/%e7%bf%bb%e8%af%91%e4%bb%8e-r60-%e5%88%b0-go-1/" title="[翻译]从 r60 到 Go 1">阅读全文——共2016字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>Go1 发布的日子越来越近，Golang 社区就像将开了的山泉水一样，泊泊的不断传来各种关于 Go1 的声音。<br />
这篇文章总结得比较完整，很清晰，随即翻译于此。<br />
原文：<a href="http://gophersays.com/from-r60-to-go1/" target="_blank">http://gophersays.com/from-r60-to-go1/</a></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;-翻译分割线&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>Go 1 已经到门口了，伙计们，它有<a href="http://weekly.golang.org/doc/go1.html" target="_blank">许多变化</a>！</p>
<p>这里是关于你必须知道的一些重要事情：</p>
<p><a href="#the_go_command">Go 命令</a><br />
<a href="#new_map_delete_syntax">新的 map delete 语法</a><br />
<a href="#errors_have_their_own_package">Error 有了自己的包</a><br />
<a href="#rewritten_libraries">重写的库</a><br />
<a href="#new_libraries">新的库</a><br />
<span id="more-1222"></span></p>
<h1 id="the_go_command">Go 命令</h1>
<p>Go 有了新的主命令，go，用于替换其他所有旧的 go 命令：</p>
<table>
<tbody>
<tr>
<th width="50%">以前</th>
<th width="50%">现在</th>
</tr>
<tr>
<td><code>godoc</code></td>
<td><code>go doc</code></td>
</tr>
<tr>
<td><code>gofix</code></td>
<td><code>go fix</code></td>
</tr>
<tr>
<td><code>gofmt -l -w *.go</code></td>
<td><code>go fmt</code></td>
</tr>
<tr>
<td><code>goinstall</code></td>
<td><code>go get</code></td>
</tr>
<tr>
<td><code>gorun</code></td>
<td><code>go run</code></td>
</tr>
<tr>
<td><code>gotest</code></td>
<td><code>go test</code></td>
</tr>
<tr>
<td><code>govet</code></td>
<td><code>go vet</code></td>
</tr>
<tr>
<td><code>make</code></td>
<td><code>go build</code></td>
</tr>
<tr>
<td><code>make clean</code></td>
<td><code>go clean</code></td>
</tr>
<tr>
<td><code>make install</code></td>
<td><code>go install</code></td>
</tr>
</tbody>
</table>
<p>（大多数工具命令，包括 6g/8g、6l/8l、6cov/8cov、gotype、gopprof 和 6prof/8prof 现在是 go tool。参阅 go tool 查看完整列表。）</p>
<h1>别了，Makefiles</h1>
<p>Go 1 已经摒弃了 Makefiles，不管怎么说这总是个临时的解决方案。作为替代，所有的事情——包括如何获取包；如何编译；以及如何测试——都将由源代码来直接导出，这全部都是由一个环境变量控制，GOPATH。</p>
<p>为了让 Go 1 能够编译某个包，该包必须包含在 GOPATH 的路径列表中。（如果 GOPATH 没有设置，go 使用自己的目录代替。）</p>
<ul>
<li>所有编译后的二进制文剑存储于 GOPATH/bin</li>
<li>所有编译后的包存储于 GOPATH/pkg//</li>
<li>所有源代码存储于 GOPATH/src/</li>
</ul>
<p>这意味着如果有一个包 github.com/pmylund/helloworld，源代码应当保存于列出在 GOPATH 中的目录 src/github.com/pmylund/helloworld 下。当执行 go install，编译后的包会在这个 GOPATH 目录下的 pkg/<arch>/github.com/pmylund/helloworld 中出现。</p>
<p>由于这些新的约定，Go 唯一需要的配置就是 GOPATH。没有 Makefile，没有自定义脚本，也不用担心命名冲突。</p>
<p>这里有个用在构建和执行自有项目的例子，也可以避免外部代码搞乱项目的目录。（例如使用 go get）：</p>
<p>在 ~/.bash_aliases （或 ~/.bash_rc）中：</p>
<pre class="brush: bash; title: ; notranslate">
mygo=/home/patrick/projects/go
goroot=/home/patrick/apps/go
gobin=$goroot/bin:$mygo/bin
export GOPATH=$goroot:$mygo
export PATH=$PATH:$gobin
</pre>
<p>因为 Go 所在目录是 GOPATH 中列出的第一个文件夹，这将作为如 go get 命令使用的默认目标目录——除非你的项目已经重新设定了其他目录，否则这将作为你项目编译后的 bin 和 pkg 目录存放的地方。</p>
<p>（如果你没有 Go 目录的写权限，可以指定另一个作为默认目录来代替 goroot。go 会将所有新的第三方包安装到那里。）</p>
<p>（当你构建一个会导入某个包的项目时，例如 github.com/pmylund/helloworld，Go 会在 GOPATH 中列出的所有目录里查找。）</p>
<p>为了了解其背后的原理，可以参考 Russ Cox 发表在 golang-nuts 邮件列表上的叫做 <a href="https://groups.google.com/d/msg/golang-nuts/tLsxO2S4yoQ/V0vAiKbNw0sJ" title="The Go Command" target="_blank">The Go Command</a> 的消息。</p>
<h1 id="new_map_delete_syntax">新的 map delete 语法</h1>
<p>现在可以使用 delete(map, “key”) 来代替 map["key"] = nil, false。</p>
<h1 id="errors_have_their_own_package">Error 有了自己的包</h1>
<p>Error 从 os 移到了 errors。同样，error 现在是一个内建类型，因此无需导入任何东西就可以使用它。</p>
<table>
<tbody>
<tr>
<th width="50%">以前</th>
<th width="50%">现在</th>
</tr>
<tr>
<td><code>os.Error</code></td>
<td><code>error</code></td>
</tr>
<tr>
<td><code>os.NewError(text string) os.Error</code></td>
<td><code>errors.New(text string) error</code></td>
</tr>
<tr>
<td><code>err.String() string</code></td>
<td><code>err.Error() string</code></td>
</tr>
</tbody>
</table>
<h1>重构的库</h1>
<p>下面的表格列出了新旧包的导入路径。（所有这些都可以用 go fix 自动修复。）</p>
<h1 id="rewritten_libraries">重写的库</h1>
<table>
<tbody>
<tr>
<th>包</th>
<th>变化</th>
</tr>
<tr>
<td><code>strconv</code></td>
<td><a href="http://weekly.golang.org/doc/go1.html#strconv">明显的重构</a></td>
</tr>
<tr>
<td><code>template</code></td>
<td>用拥有全新 API 的 <code><a href="http://weekly.golang.org/pkg/text/template/">text/template</a></code> 替换</td>
</tr>
<tr>
<td><code>time</code></td>
<td><a href="http://weekly.golang.org/doc/go1.html#time">完全重新设计</a></td>
</tr>
<tr>
<td><code>url</code></td>
<td>移动到 <code>net/url</code> 并做了 <a href="http://weekly.golang.org/doc/go1.html#url">若干修改</a>，最明显的是 <code>url.URL</code> 中的 <code>URL.Raw</code> 已经移除，并且应当用 <code>URL.String()</code> 作为代替</td>
</tr>
</tbody>
</table>
<h1 id="new_libraries">新的库</h1>
<table>
<tbody>
<tr>
<th>包</th>
<th>描述</th>
</tr>
<tr>
<td><code><a href="http://weekly.golang.org/pkg/database/sql/">database/sql</a></code></td>
<td>用于操作关系数据库的标准接口（已经存在的驱动有 SQLite、MySQL、PostgreSQL 等等）</td>
</tr>
<tr>
<td><code><a href="http://weekly.golang.org/pkg/html/template/">html/template</a></code></td>
<td><code>text/template</code> 的一个 XSS-safe 封装</td>
</tr>
</tbody>
</table>
<p>这并未涵盖 Go 1 中所有的语言和包的变化。请参阅 <a href="http://weekly.golang.org/doc/go1.html" target="_blank">Go 1 发布说明</a>（仍在进行中）和 <a href="http://weekly.golang.org/doc/devel/weekly.html" target="_blank">weekly 快照历史</a>了解更多信息。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2012/02/%e7%bf%bb%e8%af%91%e4%bb%8e-r60-%e5%88%b0-go-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[翻译]1K 玫瑰花</title>
		<link>http://www.mikespook.com/2012/02/%e3%80%90%e7%bf%bb%e8%af%91%e3%80%911k-%e7%8e%ab%e7%91%b0%e8%8a%b1/</link>
		<comments>http://www.mikespook.com/2012/02/%e3%80%90%e7%bf%bb%e8%af%91%e3%80%911k-%e7%8e%ab%e7%91%b0%e8%8a%b1/#comments</comments>
		<pubDate>Wed, 08 Feb 2012 09:22:14 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[Stardy & Research]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[rose]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/?p=1202</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
这篇文章介绍了使用 canvas 的绘图功能绘制一个 3D 玫瑰。很有特色，随翻译于此。

在 Valentine&#8217;s Day 即将来临之际，希望能给诸位死 coder 一点点好运气……

原文在此：http://www.romancortes.com/blog/1k-rose/

<span class="readmore"><a href="http://www.mikespook.com/2012/02/%e3%80%90%e7%bf%bb%e8%af%91%e3%80%911k-%e7%8e%ab%e7%91%b0%e8%8a%b1/" title="[翻译]1K 玫瑰花">阅读全文——共5559字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>这篇文章介绍了使用 canvas 的绘图功能绘制一个 3D 玫瑰。很有特色，随翻译于此。<br />
在 Valentine&#8217;s Day 即将来临之际，希望能给诸位死 coder 一点点好运气……</p>
<p>原文在此：<a href="http://www.romancortes.com/blog/1k-rose/" target="_blank">http://www.romancortes.com/blog/1k-rose/</a></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;-翻译分隔线&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
<img class="alignright" src="http://www.romancortes.com/ficheros/rose.jpg" alt="" width="510" height="310" /><br />
我参加了 <a title="js1k" href="http://js1k.com/2012-love/" target="_blank">js1k</a> 组织的关于“爱”的第四次主题活动。提交了一个静态图片，由程序生成的 3D 玫瑰花。你可以<a href="http://js1k.com/2012-love/demo/1022" target="_blank">在这里找到它</a>。</p>
<p>它是用蒙特卡洛方法显式分段采样生成 3D 曲面。我将在这个文章中逐步解释所有的要点。<br />
<span id="more-1202"></span></p>
<h1>蒙特卡洛方法的简短说明</h1>
<p>蒙特卡洛方法是一个强大到令人难以置信的工具。我经常在各种函数最优化和采样问题中使用它，当你可以运行大量 CPU 计算，但是没有设计和编写算法的时间的时候，它们工作起来就像魔法一样。在玫瑰花的例子中，它是优化代码体积的有用工具。</p>
<p>如果你对于蒙特卡洛方法不怎么了解，可以在 Wikipedia 上阅读这篇<a href="http://en.wikipedia.org/wiki/Monte_carlo_method" target="_blank">相当棒的文章</a>。</p>
<h1>显式曲面和采样/绘制</h1>
<p>为了定义玫瑰花的形状，我使用了多种显式定义曲面。一共使用了 31 个曲面：24 个花瓣，4 个萼片（花瓣周围的小叶子），2 个叶子，还有一个用于玫瑰花的枝干。</p>
<p>那么这些显式曲面是如何工作的呢？很简单，接下来展示一个 2D 例子：</p>
<p>首先定义显式曲面函数：</p>
<pre class="brush: jscript; title: ; notranslate">
function surface(a, b) {  // a 和 b 参数范围从 0 到 1。
    return {
        x: a*50,
        y: b*50
    };
    // 这个曲面将是一个 50x50 单位尺寸的正方形。
}
</pre>
<p>然后是绘制的代码：</p>
<pre class="brush: jscript; title: ; notranslate">
var canvas = document.body.appendChild(document.createElement(&quot;canvas&quot;)),
    context = canvas.getContext(&quot;2d&quot;),
    a, b, position;

// 现在将用参数 a 和 b 对曲面按照 .1 间隔进行采样：

for (a = 0; a &lt; 1; a += .1) {
    for (b = 0; b &lt; 1; b += .1) {
        position = surface(a, b);
        context.fillRect(position.x, position.y, 1, 1);
    }
}
</pre>
<p>结果为：</p>
<p><img src="http://www.romancortes.com/ficheros/rose-surface-drawing-1.gif" alt="" /></p>
<p>现在，让我们尝试用密度更高的采样间隔（更小间隔 = 更高密度）：</p>
<p><img src="http://www.romancortes.com/ficheros/rose-surface-drawing-2.gif" alt="" /></p>
<p>你已经看到了，当采样密度越来越高时，点和点之间越来越近，直到一个点和它临近的点之间的距离小于一个像素，这时屏幕上的曲面就完全被填充了（看 0.01）。这时，无论怎样提高密度也不会带来视觉上的变化，那么刚刚绘制的的区域就是已经被填充过的（比较 0.01 和 0.001 的结果）。</p>
<p>好，现在让我们重新定义曲面函数来绘制一个圆。有各种办法来实现，我会用这个公式：(x-x0)^2 + (y-y0)^2 < radius^2 这里的 (x0, y0) 是圆心：</p>
<pre class="brush: jscript; title: ; notranslate">
function surface(a, b) {
    var x = a * 100,
        y = b * 100,
        radius = 50,
        x0 = 50,
        y0 = 50;

    if ((x &#8211; x0) * (x &#8211; x0) + (y &#8211; y0) * (y &#8211; y0) &lt; radius * radius) {
        // 圆里
        return {
            x: x,
            y: y
        };
    } else {
        // 圆外
        return null;
    }
}
</pre>
<p>由于我屏蔽了圆外的点，所以要在采样中加入一个条件：</p>
<pre class="brush: jscript; title: ; notranslate">
if (position = surface(a, b)) {
    context.fillRect(position.x, position.y, 1, 1);
}
</pre>
<p>结果为：</p>
<p><img src="http://www.romancortes.com/ficheros/rose-surface-drawing-3.gif" alt="" /></p>
<p>刚才已经说了，有各种途径来定义圆，有些无需在采样中进行屏蔽。这里会展示其中一个办法，不过仅仅是一个提示；在接下来的文章中不会使用它：</p>
<pre class="brush: jscript; title: ; notranslate">
function surface(a, b) {
    // 使用圆的极坐标
    var angle = a * Math.PI * 2,
        radius = 50,
        x0 = 50,
        y0 = 50;

    return {
        x: Math.cos(angle) * radius * b + x0,
        y: Math.sin(angle) * radius * b + y0
    };
}
</pre>
<p><img src="http://www.romancortes.com/ficheros/rose-surface-drawing-3.gif" alt="" /></p>
<p>（这个方法需要比前一个方法更高的采样来填充这个圆）</p>
<p>好，现在来让圆变形，这样让它看起来更像一片花瓣：</p>
<pre class="brush: jscript; title: ; notranslate">
function surface(a, b) {
    var x = a * 100,
        y = b * 100,
        radius = 50,
        x0 = 50,
        y0 = 50;

    if ((x - x0) * (x - x0) + (y - y0) * (y - y0) &lt; radius * radius) {
        return {
            x: x,
            y: y * (1 + b) / 2 // 变形
        };
    } else {
        return null;
    }
}
</pre>
<p>结果为：</p>
<p><img src="http://www.romancortes.com/ficheros/rose-surface-drawing-4.gif" alt="" /></p>
<p>好，现在这个看起来更像是玫瑰花的花瓣的形状了。我建议你对变形多进行一些调整。你可以使用任何数学函数来实现，加减乘除、sin、 cos、乘方……任何函数。尝试修改这个函数，就能得到许多的形状（有的会很有趣）。</p>
<p>现在我为其增加一些颜色，对曲面添加颜色数据：</p>
<pre class="brush: jscript; title: ; notranslate">
function surface(a, b) {
    var x = a * 100,
        y = b * 100,
        radius = 50,
        x0 = 50,
        y0 = 50;

    if ((x - x0) * (x - x0) + (y - y0) * (y - y0) &lt; radius * radius) {
        return {
            x: x,
            y: y * (1 + b) / 2,
            r: 100 + Math.floor((1 - b) * 155), // 这会产生一个梯度
            g: 50,
            b: 50
        };
    } else {
        return null;
    }
}

for (a = 0; a &lt; 1; a += .01) {
    for (b = 0; b &lt; 1; b += .001) {
        if (point = surface(a, b)) {
            context.fillStyle = &quot;rgb(&quot; + point.r + &quot;,&quot; + point.g + &quot;,&quot; + point.b + &quot;)&quot;;
            context.fillRect(point.x, point.y, 1, 1);
        }
    }
}
</pre>
<p>结果为：</p>
<p><img src="http://www.romancortes.com/ficheros/rose-surface-drawing-5.jpg" alt="" /></p>
<p>铛！铛！铛！铛！隆重推出，有颜色的花瓣！</p>
<h1>3D 曲面和透视投影</h1>
<p>定义 3D 曲面是直接明了的：只要为曲面函数添加 z 属性。例如，接下来定义一个管道/圆柱体：</p>
<pre class="brush: jscript; title: ; notranslate">
function surface(a, b) {
    var angle = a * Math.PI * 2,
        radius = 100,
        length = 400;

    return {
        x: Math.cos(angle) * radius,
        y: Math.sin(angle) * radius,
        z: b * length - length / 2, // 通过减掉 length/2，使得这个管道的中心在 (0, 0, 0)
        r: 0,
        g: Math.floor(b * 255),
        b: 0
    };
}
</pre>
<p>现在，添加透视投影，首先定义一个摄影机：</p>
<p><img src="http://www.romancortes.com/ficheros/rose-camera.gif" alt="" /></p>
<p>我将摄影机放置于 (0, 0, cameraZ)，我将摄影机到画布的距离叫做“perspective”。我认为画布在 x/y 平面上，中心点是 (0, 0, cameraZ + perspective)。现在，每个采样点将会投影到画布：</p>
<pre class="brush: jscript; title: ; notranslate">
var pX, pY,  // 在画布上投影的 x 和 y 坐标
    perspective = 350,
    halfHeight = canvas.height / 2,
    halfWidth = canvas.width / 2,
    cameraZ = -700;

for (a = 0; a &lt; 1; a += .001) {
    for (b = 0; b &lt; 1; b += .01) {
        if (point = surface(a, b)) {
            pX = (point.x * perspective) / (point.z - cameraZ) + halfWidth;
            pY = (point.y * perspective) / (point.z - cameraZ) + halfHeight;
            context.fillStyle = &quot;rgb(&quot; + point.r + &quot;,&quot; + point.g + &quot;,&quot; + point.b + &quot;)&quot;;
            context.fillRect(pX, pY, 1, 1);
        }
    }
}
</pre>
<p>这个结果为：</p>
<p><img src="http://www.romancortes.com/ficheros/rose-tube1.jpg" alt="" /></p>
<h1>Z-buffer</h1>
<p>在计算机图形学中 z-buffer 是相当常见的技术，用于在远离摄影机的已经被绘制的点上绘制接近摄影机的点。它的工作方式是维护一个图像上已经画过的像素的数组。</p>
<p><img src="http://www.romancortes.com/ficheros/rose-z-buffer.jpg" alt="" /></p>
<p>这是玫瑰花的可视的 z-buffer，黑色是距离摄影机远的，白色是距离近的。</p>
<p>实现为：</p>
<pre class="brush: jscript; title: ; notranslate">
var zBuffer = [],
    zBufferIndex;

for (a = 0; a &lt; 1; a += .001) {
    for (b = 0; b &lt; 1; b += .01) {
        if (point = surface(a, b)) {
            pX = Math.floor((point.x * perspective) / (point.z - cameraZ) + halfWidth);
            pY = Math.floor((point.y * perspective) / (point.z - cameraZ) + halfHeight);
            zBufferIndex = pY * canvas.width + pX;
            if ((typeof zBuffer[zBufferIndex] === &quot;undefined&quot;) || (point.z &lt; zBuffer[zBufferIndex])) {
                zBuffer[zBufferIndex] = point.z;
                context.fillStyle = &quot;rgb(&quot; + point.r + &quot;,&quot; + point.g + &quot;,&quot; + point.b + &quot;)&quot;;
                context.fillRect(pX, pY, 1, 1);
            }
        }
    }
}
</pre>
<h1>旋转圆柱体</h1>
<p>你可以使用任何向量旋转方法。在玫瑰花的例子中，我使用 <a href="http://en.wikipedia.org/wiki/Euler_angles" target="_blank">Euler 旋转</a>。来实现一个基于 Y 轴的旋转：</p>
<pre class="brush: jscript; title: ; notranslate">
function surface(a, b) {
    var angle = a * Math.PI * 2,
        radius = 100,
        length = 400,
        x = Math.cos(angle) * radius,
        y = Math.sin(angle) * radius,
        z = b * length - length / 2,
        yAxisRotationAngle = -.4, // in radians!
        rotatedX = x * Math.cos(yAxisRotationAngle) + z * Math.sin(yAxisRotationAngle),
        rotatedZ = x * -Math.sin(yAxisRotationAngle) + z * Math.cos(yAxisRotationAngle);

    return {
        x: rotatedX,
        y: y,
        z: rotatedZ,
        r: 0,
        g: Math.floor(b * 255),
        b: 0
    };
}
</pre>
<p>结果为：</p>
<p><img src="http://www.romancortes.com/ficheros/rose-tube2.jpg" alt="" /></p>
<h1>蒙特卡洛采样</h1>
<p>在文章中已经使用了基于间隔的采样。它需要对每个曲面设定合适的间隔。如果间隔大，渲染会很快，但是曲面可能未被完全填充而存在空洞。另一方面，如果间隔过小，渲染会超过透视投影所需的时间。</p>
<p>所以，还是切换到蒙特卡洛采样吧：</p>
<pre class="brush: jscript; title: ; notranslate">
var i;

window.setInterval(function () {
    for (i = 0; i &lt; 10000; i++) {
        if (point = surface(Math.random(), Math.random())) {
            pX = Math.floor((point.x * perspective) / (point.z - cameraZ) + halfWidth);
            pY = Math.floor((point.y * perspective) / (point.z - cameraZ) + halfHeight);
            zBufferIndex = pY * canvas.width + pX;
            if ((typeof zBuffer[zBufferIndex] === &quot;undefined&quot;) || (point.z &lt; zBuffer[zBufferIndex])) {
                zBuffer[zBufferIndex] = point.z;
                context.fillStyle = &quot;rgb(&quot; + point.r + &quot;,&quot; + point.g + &quot;,&quot; + point.b + &quot;)&quot;;
                context.fillRect(pX, pY, 1, 1);
            }
        }
    }
}, 0);
</pre>
<p>现在，参数 a 和 b 被设置为两个随机值。对足够多的点进行采样，曲面就可以利用这种方法填充。多亏了间隔采样，我可以确定每次用 10000 个点绘制，然后更新屏幕。</p>
<p>特别说明一下，完全填充一个曲面仅仅需要保证伪随机数生成器的品质够好。在某些浏览器中，Math.random 是按照<a href="http://en.wikipedia.org/wiki/Linear_congruential_generator" target="_blank">线性一致生成器</a>实现的，而这可能在某些曲面上产生一些问题。如果你在采样中有较好的伪随机噪声生成的需求，你可以使用更高品质的如 Mersenne Twister （这里有其 JS 实现），或者在某些浏览器里可以使用的密码随机生成器。同样使用<a href="http://en.wikipedia.org/wiki/Low-discrepancy_sequence" target="_blank">低差异数序列</a>也是很好的解决方案。</p>
<h1>总结</h1>
<p>为了完成这个玫瑰花，花朵的每个部分，每个曲面，需要同时进行渲染。我为函数添加了第三个参数用于确定返回玫瑰花的哪个部分的点。数学上来说，这是一个分段函数，每个片段对应玫瑰花的一部分。在花瓣的部分，我使用旋转和拉伸/变形来创建所有花瓣。所有都是用文章中提及的方法混合来完成的。</p>
<p>当然通过采样建立显式曲面是众所周知的方法，并且是最古老的 3D 图形方法之一，在艺术用途中像我这样使用分段/蒙特卡洛/z-buffer 已经非常少见了。没什么创新，对于实际生活也不怎么有用，但是非常适合 js1k 这种简单并且小尺寸的要求。</p>
<p>通过这篇文章，我希望能够激发读者在计算机图形学上的兴趣来进行尝试，并且在不同的渲染方法中找到乐趣。在图形学的世界中探索和玩耍是一件令人兴奋的事情。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2012/02/%e3%80%90%e7%bf%bb%e8%af%91%e3%80%911k-%e7%8e%ab%e7%91%b0%e8%8a%b1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[翻译]Goroutine性能测试</title>
		<link>http://www.mikespook.com/2012/01/goroutine%e6%80%a7%e8%83%bd%e6%b5%8b%e8%af%95/</link>
		<comments>http://www.mikespook.com/2012/01/goroutine%e6%80%a7%e8%83%bd%e6%b5%8b%e8%af%95/#comments</comments>
		<pubDate>Fri, 06 Jan 2012 03:55:10 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[Golang]]></category>
		<category><![CDATA[golang]]></category>
		<category><![CDATA[goroutine]]></category>
		<category><![CDATA[性能]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/?p=1177</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
原文在此：http://en.munknex.net/2011/12/golang-goroutines-performance.html

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;翻译分割线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;

概述

<span class="readmore"><a href="http://www.mikespook.com/2012/01/goroutine%e6%80%a7%e8%83%bd%e6%b5%8b%e8%af%95/" title="[翻译]Goroutine性能测试">阅读全文——共1952字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>原文在此：<a href="http://en.munknex.net/2011/12/golang-goroutines-performance.html" target="_blank">http://en.munknex.net/2011/12/golang-goroutines-performance.html</a></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;翻译分割线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<h1>概述</h1>
<p>在这篇文章里，我将尝试评估 goroutine 的性能。goroutine 是类似轻量级线程的东西。为了提供原生的多任务，它（协同 channel 一起）被内建于Go中。</p>
<p>文档告诉我们：</p>
<blockquote><p>它实际上是在同一个地址空间里创建成百上千个 goroutine。</p></blockquote>
<p>因此，这个文章的重点就是测试并明确在如此巨大的并发运行函数的情况下所能承受的性能压力上限。<br />
<span id="more-1177"></span></p>
<h1>内存</h1>
<p>创建一个新的goroutine所需空间并未记录在文档中。只是说需要几千字节。在不同的机制下测试，帮助确认这个数值为4—4.5kB。因此，5GB差不多足够运行一百万个goroutine。</p>
<h1>性能</h1>
<p>让我们算算在一个 goroutine 里运行函数会损失多少的性能吧。可能你已经知道这非常简单——只要在函数调用前添加 go 关键字：</p>
<pre class="brush: cpp; title: ; notranslate">
go testFunc()
</pre>
<p>goroutine 复用于线程。默认情况下，如果没有设定 GOMAXPROCS 环境变量，程序只使用一个线程。为了利用全部 CPU 内核，则必须制定它的值。例如：</p>
<pre class="brush: bash; title: ; notranslate">
export GOMAXPROCS=2
</pre>
<p>这个值在运行时使用。因此没有必要在每次修改这个值之后，重新编译程序。</p>
<p>以我的推断，大多数时间花费在创建 goroutine，切换它们，以及从一个线程迁移 goroutine 到另外的线程，还有在不同的线程之间的 goroutine 进行通讯。为了避免无尽的论述，让我们从仅用一个线程的情况开始。</p>
<p>所有测试都是在我的 nettop（译注：英特尔公司的低成本简易台式机解决方案）上完成的：</p>
<ul>
<li>Atom D525 Dual Core 1.8 GHz</li>
<li>4Gb DDR3</li>
<li>Go r60.3</li>
<li>Arch Linux x86_64</li>
</ul>
<h1>方法</h1>
<p>这是测试函数生成器：</p>
<pre class="brush: cpp; title: ; notranslate">
func genTest (n int) func (res chan &lt;- interface {}) {
        return func(res chan &lt;- interface {}) {
                for i := 0; i &lt; n; i++ {
                        math.Sqrt(13)
                }
                res &lt;- true
        }
}
</pre>
<p>然后这里是一系列分别计算 sqrt(13) 1、10、100、1000 和 5000 次的函数集合：</p>
<pre class="brush: cpp; title: ; notranslate">
testFuncs := [] func (chan &lt;- interface {}) { genTest(1), genTest(10), genTest(100), genTest(1000), genTest(5000) }
</pre>
<p>我将每个函数在循环中执行 X 遍，然后在 goroutine 中执行 X 遍。然后比较结果。当然，应当留意垃圾回收。为了降低其带来的影响，我在 goroutine 结束后显式调用了 runtime.GC() 并记录结束时间。当然，为了测试精确性，每个测试执行了许多遍。整个运行时间用了大约 16 小时。</p>
<h1>一个线程</h1>
<pre class="brush: bash; title: ; notranslate">
export GOMAXPROCS=1
</pre>
<p><img src="https://lh4.googleusercontent.com/-tJyRcozfSi4/Tv4c-32C8LI/AAAAAAAABmw/2eBz0cWFWaw/s980/BOlyT.png" alt="goroutine 性能测试 1.1" /></p>
<p>图表显示在 goroutine 中运行的 sqrt() 计算工作大约比在函数中运行慢四倍。</p>
<p>来看看剩余的四个函数的情况：</p>
<p><img src="https://lh3.googleusercontent.com/-SdI6VAsosG0/Tv4c9x9NpDI/AAAAAAAABmo/c6EVJs4scHY/s983/bdJiZ.png" alt="goroutine 性能测试 1.2" /></p>
<p>你会注意到，即使并发执行70万 goroutine 也不会使得性能下降到 80% 以下。现在是最值得敬佩的地方。从 sqrt()x1000 开始，总体消耗低于 2%。5000 次——只有 1%。看起来这个数值与 goroutine 的数量无关！因此唯一的制约因素是内存。</p>
<h1>概要：</h1>
<p>如果互不依赖的代码的执行时间高于计算平方跟的10倍，并且你希望它并发执行，应毫不犹豫的让其在 goroutine 中运行。虽然，可以轻松的将10或者100个这样的代码放在一起，不过损失的性能仅仅分别是 20% 和 2%。</p>
<h1>多线程</h1>
<p>现在来看看当我们希望使用若干个处理器内核时的情况。在我的用例中是 2 个：</p>
<pre class="brush: bash; title: ; notranslate">
export GOMAXPROCS=2
</pre>
<p>再次执行我们的测试程序：</p>
<p><img src="https://lh3.googleusercontent.com/--Oopi4ZD_BU/Tv4c8s6C7JI/AAAAAAAABmg/i6I2GFF6JeI/s977/zcv7K.png" alt="goroutine 性能测试 2.1" /></p>
<p>这里你会发现，尽管内核数增加了一倍，但是前两个函数的运行时间却增加了！这极可能是在线程之间移动比执行它们的开销要大得多。：）当前的调度器还不能处理，不过 Go 的开发者承诺在未来会解决这种情况。</p>
<p><img src="https://lh4.googleusercontent.com/-f7R2zsoajNI/Tv4c7W6Um4I/AAAAAAAABmY/qY6C6eYQOzI/s981/Jp3lZ.png" alt="goroutine 性能测试 2.2" /></p>
<p>你已经看到了，最后的两个函数完全使用了两个核。在我的 nettop 上，他们的执行时间分别是 ~45µs 和 ~230µs。</p>
<h1>总结</h1>
<p>尽管这是一个年轻的语言，并且有着一个临时的调度器实现，goroutine 的性能让人觉得兴奋。尤其是与 Go 的简单易用结合起来的时候。这令我印象深刻。感谢 Go 开发团队！</p>
<p>当运行时间少于 1µs 我会在执行 goroutine 之前深思熟虑一下，而如果运行时间超过 1ms，那就决不犹豫的使用 goroutine 了。：）</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2012/01/goroutine%e6%80%a7%e8%83%bd%e6%b5%8b%e8%af%95/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>我们要什么样的.NET程序员</title>
		<link>http://www.mikespook.com/2011/12/%e6%88%91%e4%bb%ac%e8%a6%81%e4%bb%80%e4%b9%88%e6%a0%b7%e7%9a%84-net%e7%a8%8b%e5%ba%8f%e5%91%98/</link>
		<comments>http://www.mikespook.com/2011/12/%e6%88%91%e4%bb%ac%e8%a6%81%e4%bb%80%e4%b9%88%e6%a0%b7%e7%9a%84-net%e7%a8%8b%e5%ba%8f%e5%91%98/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 04:47:13 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[My life]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[团队]]></category>
		<category><![CDATA[扯淡]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/?p=1170</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
外刊IT评论今天抽风，发了很久以前的一篇博文的译文出来：《为什么我们不要.NET程序员》。本文一发，各种口水接踵而至。这篇文章实际上是《CEO Friday: Why we don’t hire .NET programmers》的译文，原文作者在发文后的两天的时间里不断的根据读者反馈对文章进行了更新和补充。但是遗憾的是外刊IT评论却未能翻译完整（不，不，你们不要指望我会翻译剩下的部分，我对此毫无兴趣。），这使得这篇很有闪光点的文章立刻变成了“孰优孰劣”的口水文章了。

看看中文翻译后的评论吧：

<span class="readmore"><a href="http://www.mikespook.com/2011/12/%e6%88%91%e4%bb%ac%e8%a6%81%e4%bb%80%e4%b9%88%e6%a0%b7%e7%9a%84-net%e7%a8%8b%e5%ba%8f%e5%91%98/" title="我们要什么样的.NET程序员">阅读全文——共2236字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p><a href="http://www.aqee.net/" target="_blank">外刊IT评论</a>今天抽风，发了很久以前的一篇博文的译文出来：《<a href="http://www.aqee.net/why-we-dont-hire-net-programmers/" target="_blank">为什么我们不要.NET程序员</a>》。本文一发，各种口水接踵而至。这篇文章实际上是《<a href="http://blog.expensify.com/2011/03/25/ceo-friday-why-we-dont-hire-net-programmers/" target="_blank">CEO Friday: Why we don’t hire .NET programmers</a>》的译文，原文作者在发文后的两天的时间里不断的根据读者反馈对文章进行了更新和补充。但是遗憾的是外刊IT评论却未能翻译完整（不，不，你们不要指望我会翻译剩下的部分，我对此毫无兴趣。），这使得这篇很有闪光点的文章立刻变成了“孰优孰劣”的口水文章了。</p>
<p>看看中文翻译后的评论吧：</p>
<blockquote><p>有一种人，自己写不出东西，就怪能写出东西的人使用的工具太先进</p>
<p>弱智文章</p>
<p>SB文章，还以为有什么高深的见解，完全是个自以为是的家伙。至多不过是了解了.net之外某一些东西，对自己完全不了解的东西大放厥词还放出优越感来了。</p>
<p>俺作为一名.NET程序员，鉴定结果为，“此文纯属标题党”，一笑而过~~~</p></blockquote>
<p>我对留下这些评论的程序员感到悲哀……</p>
<p>我们的团队也有着大量的.NET工程师，我每天与他们共处。他们中间有聪明的、优秀的、稳重的工程师；也有躁动的、浮夸的、随意的编码人员。他们能够产生符合设计规范和要求的代码和系统；也会在不经意之间向系统引入致命 bug 而导致生产环境的崩溃。他们其实与依赖其他技术架构的程序员并无多大的不同。</p>
<p><span id="more-1170"></span></p>
<p>早上，我看到那篇中文翻译的时候，在公司的讨论组里向大家分享了译文和原文。特别提示了，重点看看原文后面的评论。发出去后，我本以为会有人回应支持或者反对。但是没有任何一个人对那些内容进行赞扬或者批评。后来，一个比较了解我的同事私下跟我说“估计一大部分人心里不是滋味”，“一下看到标题，还有你的身份”。好吧，可能许多人心里十分不悦，但是碍于我的“身份”不便表露？我毫不介意的跟大家分享一下，我在国家正式的定义中的身份是“群众”。</p>
<p>我不知道会有多少团队的成员看到本文，我也无从知道他们真实的想法。不过，我可以谈谈什么样的.NET程序员是我们需要.的。</p>
<p>当然为了避免在我的博客上有人指责我由于“根本不了解.NET技术，也不懂windows平台，没有资格来说三道四”。我简要介绍一下我对windows平台和.NET的了解情况。</p>
<p>跟大部分人一样，我对计算机和IT的认识是从windows开始的。win32.hlp 这个帮助文件我想大部分年轻的.NET程序员从来没看过，甚至从来没听过。COM/COM+对于.NET平台就像战国时代的二轮马车一样遥远。PE文件结构就是放在博物馆里的竹简一般，除了历史学家会感兴趣之外毫无用处……我能举的例子还有很多，而这些在我被开源和 Linux 这个魔鬼抓去之前，是每日在学习和探索的东西。哦，忘记说了，.NET 我也不算是毫无认知。至少，在有史可查的范围内，我开源了国内第一个用C#编写的针对性SQL Injection自动化注入工具，如果没记错，那是01还是02年左右的时间。好吧，现在我是否有资格来跟大家探讨这个事情了呢？</p>
<p>事情还是从如何做出一个1.7盎司的汉堡说起……</p>
<p>作为一个.NET程序员，或者特指正在进行互联网开发的.NET程序员，你是否知道我们面对的不仅仅是1.6盎司、1.7盎司的汉堡这么简单的事情？你是否知道互联网这场盛宴不仅仅是做一两个汉堡这么简单？思考的方式有许多种，你是否陷入了做汉堡需要在哪里获得合适的面包、肉饼、洗好的蔬菜、酱料的迷题中，而忘记了手边就有面粉、烤炉，冰箱里有冷藏的鲜肉（你看，已经无需自己杀猪宰牛了），放在窗台的蔬菜上面的泥土和青虫说明菜叶相当的新鲜。</p>
<p>换句话说：你们是否陷入过疯狂的在.NET库中寻找一个合适的类，而忘记去看看开源社区或者第三方是否有提供更好的服务？是否执意要在微软提供的架构体系下实现一些特别的需求，其实那些需求只要一些跳出框架的小小的技巧？是否在看到业内的某些关于技术创新的一句话新闻时，就在心中暗想“这有什么先进的，.NET早有了”，而没有深入的研究为什么这一创新能够成为业内的新闻？</p>
<p>当然，如果对于这些你都有自己可以解释的答案，那么你或许是我们所需要的那种.NET程序员！</p>
<p>如果：你不但能够使用服务器端控件，还能说出其封装的底层原理；不但能够在IIS里建立应用，还能弄明白从客户在浏览器输入你的应用的地址，到他得到满意的结果，这中间每个环节隐含的细节；不但会用WCF来实现功能，也清晰的理解其中的缘由，尤其的，清晰的了解SOA应用于互联网的利弊；不但会在MSDN中查询疑难问题，也会在Google中参考出现在Mono中的类似的解决办法。</p>
<p>那么你应该是我们所需要的那种.NET程序员！</p>
<p>当然，更为优秀的，是那些能够在.NET框架下开发，却从不自称为.NET程序员的家伙们。他们不会将自己限定在某种技术、某种平台；他们热爱技术，热爱生活；他们有着像猫一样的好奇心，即便是这好奇心可能杀死他们也从不畏惧，他们同样有九条命；他们乐于钻研.NET技术，但是也会吸取其他平台的精华……</p>
<p>对于这样的人，我知道是可遇不可求的……</p>
<p>.NET、JAVA、PHP、Python……这些技术难道就没有一点贯通的地方？难道我们在自我介绍的时候不能换个说法：</p>
<blockquote><p>我，是程序员，在现在这个阶段我对.NET的使用积累的经验更多一些。</p></blockquote>
<p>是的，我正是这个意思，程序员可以有各种标签，但是别让标签左右了工程师的灵魂。做技术的主人还是奴隶，只是个人的选择而已。</p>
<p>这或许能够阐述我们要什么样的.NET程序员了吧？</p>
<p>我们需要的是熟悉.NET的程序员，我们真得不要“.NET程序员”。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2011/12/%e6%88%91%e4%bb%ac%e8%a6%81%e4%bb%80%e4%b9%88%e6%a0%b7%e7%9a%84-net%e7%a8%8b%e5%ba%8f%e5%91%98/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[翻译]Go 指南</title>
		<link>http://www.mikespook.com/2011/11/%e7%bf%bb%e8%af%91go-%e6%8c%87%e5%8d%97/</link>
		<comments>http://www.mikespook.com/2011/11/%e7%bf%bb%e8%af%91go-%e6%8c%87%e5%8d%97/#comments</comments>
		<pubDate>Wed, 16 Nov 2011 15:03:17 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[Golang]]></category>
		<category><![CDATA[golang]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/?p=1162</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
英文版本是《A Tour of Go》。我看过之后觉得这种学习体验非常棒，随即按照规则翻译了中文版本：

《Go 指南》

这个中文版本是部署在 GAE 上的，由于受到功夫网的影响，国内用户无法正常访问。所以，大家八仙过海吧。

<span class="readmore"><a href="http://www.mikespook.com/2011/11/%e7%bf%bb%e8%af%91go-%e6%8c%87%e5%8d%97/" title="[翻译]Go 指南">阅读全文——共498字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>英文版本是《<a title="A Tour of Go" href="http://tour.golang.org" target="_blank">A Tour of Go</a>》。我看过之后觉得这种学习体验非常棒，随即按照规则翻译了中文版本：</p>
<p>《<a title="Go 指南" href="http://go-tour-zh.appspot.com" target="_blank">Go 指南</a>》</p>
<p>这个中文版本是部署在 GAE 上的，由于受到功夫网的影响，国内用户无法正常访问。所以，大家八仙过海吧。</p>
<p>（人还在这里，心已经出去了……）</p>
<p>由于许多原因，可能有的朋友无法一窥墙外之物。也可以通过源码将指南安装到本地使用。指南中有详细的说明，转发到这里，诸位自便吧。代码我托管在了 <a href="http://bitbucket.org/mikespook/go-tour-zh" target="_blank">http://bitbucket.org/mikespook/go-tour-zh</a>。</p>
<p><span id="more-1162"></span></p>
<h2>离线 Go 指南</h2>
<div> 该指南同样可以作为独立的程序用在没有互联网接入的情况下。</div>
<p>独立运行的指南更快，同时它在你本地的设备上构建和编译代码。它同时包括了一些在沙盒版本中没有的增强体验。</p>
<p>为了在本地运行指南首先要<a href="http://golang.org/doc/install.html" target="_blank">安装 Go</a>（最后的稳定版本，<code>release.r60</code>），然后使用 <a href="http://golang.org/cmd/goinstall/" target="_blank">goinstall</a> 安装 <a href="http://code.google.com/p/go-tour/" target="_blank">gotour</a>：</p>
<pre>    goinstall go-tour.googlecode.com/hg/gotour</pre>
<p>也可以安装<a href="http://bitbucket.org/mikespook/go-tour-zh/" target="_blank">中文版本</a>：</p>
<pre>    goinstall bitbucket.org/mikespook/go-tour-zh/gotour</pre>
<p>最后执行安装产生的 <code>gotour</code> 执行文件。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2011/11/%e7%bf%bb%e8%af%91go-%e6%8c%87%e5%8d%97/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>[翻译]S代表着Simple</title>
		<link>http://www.mikespook.com/2011/11/s%e4%bb%a3%e8%a1%a8%e7%9d%80simple/</link>
		<comments>http://www.mikespook.com/2011/11/s%e4%bb%a3%e8%a1%a8%e7%9d%80simple/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 03:47:31 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[My life]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[soap]]></category>
		<category><![CDATA[uddi]]></category>
		<category><![CDATA[web service]]></category>
		<category><![CDATA[wsdl]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/?p=1151</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
我从来都不是 SOAP 的拥护着。甚至，我对 xml 都会有一种天生的恐惧。别问我为啥，我也不知道。性情如此吧。

这个故事是我看过的最搞笑，也最命中 SOAP 的要害的段子。看完之后，我突然明白我为啥不那么喜欢 SOAP、WSDL、UDDI之类的了。

翻译至此，大家一起乐乐。

<span class="readmore"><a href="http://www.mikespook.com/2011/11/s%e4%bb%a3%e8%a1%a8%e7%9d%80simple/" title="[翻译]S代表着Simple">阅读全文——共3389字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>我从来都不是 SOAP 的拥护着。甚至，我对 xml 都会有一种天生的恐惧。别问我为啥，我也不知道。性情如此吧。<br />
这个故事是我看过的最搞笑，也最命中 SOAP 的要害的段子。看完之后，我突然明白我为啥不那么喜欢 SOAP、WSDL、UDDI之类的了。</p>
<p>翻译至此，大家一起乐乐。</p>
<p>原文在此：<a href="http://harmful.cat-v.org/software/xml/soap/simple" target="_blank">http://harmful.cat-v.org/software/xml/soap/simple</a></p>
<p>&#8212;&#8212;&#8212;-翻译分割线&#8212;&#8212;&#8212;-</p>
<h1>S意味着Simple</h1>
<p>Pete Lacey 编撰</p>
<p>在 Burton 团体的应用平台服务组内，支持 REST 的人和支持 SOAP 的人已经进行了很久的论战。在大多数情况下这只是外部论战的一个缩影。在最近的一次交锋中，当讨论到 SOAP 和 web 服务的复杂性时，SOAP 的一方这样说到“在之前的 WS 情形下，SOAP 确实是简单的。这也就是 S 所代表的东西。”</p>
<p>那么现在是历史课时间。这是 2000 年，一个倍受折磨的开发者遇到了一个问题……</p>
<p><span id="more-1151"></span></p>
<p>开发者：好吧，我的老板这个周末正在打高尔夫，而现在我必须“括起，闭合”这个 SOAP 驱动的企业，但是我不知道 SOAP 是什么。你们能帮助我吗，SOAP 达人？</p>
<p>SOAP 达人：没问题。首先，SOAP 表示 Simple Object Access Protocol（简单对象访问协议）。</p>
<p>开：那么它简单吗？</p>
<p>S达：就像星期天一样简单，我的朋友。</p>
<p>开：太好了，跟我讲讲。</p>
<p>S达: 那么，就像它的名字说的那样，SOAP 用于访问远程对象。</p>
<p>开：就像 CORBA？</p>
<p>S达：跟 CORBA 像极了，只是更简单。为了代替那些不能穿过防火墙的复杂的传输协议，我们使用 HTTP。同时使用 XML 来代替二进制消息格式。</p>
<p>开：我很有兴趣。给我展示一下它是如何工作的。</p>
<p>S达：没问题。首先是 SOAP 封装。它非常简单。只是由头部和内容组成的 XML 文档。而在内容里可以构造你的 RPC 调用。</p>
<p>开：那么这些全部都是关于 RPC 的？</p>
<p>S达：当然。就像我说过的，你通过在内容中设定方法名和其参数来构造 RPC。方法名是外部元素，而每个子元素作为参数。而所有的参数可以由格式说明书第 5 章定义的类型来定义。</p>
<p>开：（阅读了第 5 章）好吧，这并不太糟。</p>
<p>S达：现在，当你的服务部署了以后，你定义这个端点。</p>
<p>开：端点？</p>
<p>S达：端点，服务的地址。你 POST SOAP 封装到端点的 URL。</p>
<p>开：那么如果我 GET 端点的 URL 会发生什么？</p>
<p>S达：不知道。GET 的使用是没有定义的。</p>
<p>开：呃。那么如果我将服务移到不同的端点会发生什么？我会收到 301 返回吗？</p>
<p>S达：不。SOAP 并不使用 HTTP 返回码。</p>
<p>开：那么，当你说 SOAP 使用 HTTP，就是说 SOAP 通过 HTTP 隧道传出。</p>
<p>S达：好吧，‘隧道’是个丑陋的词汇。我们更喜欢说 SOAP 是传输层透明的。</p>
<p>开：但是 HTTP 不是传输层的。它是应用层协议。不管怎么样，SOAP 支持其他什么“传输层”？ </p>
<p>S达：好吧，官方来说没有。不过理论上支持任何方法。而有许多平台已经支持 JMS、FTP 和 SMTP。</p>
<p>开：有任何人实际在使用其他这些传输层吗？</p>
<p>S达：唔，不。不过关键是你可以这么做。</p>
<p>开: 当然。SOAPAction HTTP 头又如何，它代表什么？</p>
<p>S达：诚实来说，没有人真正确定。</p>
<p>开：还有这些‘actor’和‘mustUnderstand’属性，有人使用吗？</p>
<p>S达：不。这些没准备好。忽略它们吧。</p>
<p>开：好的，让我浏览一下。</p>
<p>（时间飞逝……）</p>
<p>开：好吧，这个基本上能够工作起来了，不过仅仅是一个点调用一个 SOAP 栈。同时，我不能说我喜欢这个远程过程调用和序列化对象的主意。</p>
<p>S达：远程过程调用！序列化对象！你从哪里得到的印象说 SOAP 是关于 RPC 的？SOAP 全部是关于基于文档的消息传递，我的朋友。</p>
<p>开：但是你刚才说——</p>
<p>S达：忘掉我说过的吧。从这里开始我们将围绕粗粒度消息——你喜欢那个名词“粗粒度”吗？消息匹配一个 XML Schema。我们将新的叫做 Document/Literal 模式，而旧的是 RPC/Encoded 模式。</p>
<p>开：XML Schema？</p>
<p>S达：哦，如今这个很流行。下一个爆发。看看吧。</p>
<p>开：（阅读了 XML Schema 说明书）我的天啊！亚历山大大帝也不能弄明白这个。</p>
<p>S达：别担心。你的工具会为你创建 schema。真的，全部都是关于工具化的。</p>
<p>开：那么这些工具会如何做呢？</p>
<p>S达：好吧，它们会反射你的代码（如果可能）并且自动生成一个兼容的 schema。</p>
<p>开：对我的代码进行反射？我之前认为它是关于文档的，而不是序列化对象。</p>
<p>S达：你没听我说吗？这全部都是工具的工作。不管怎么样，我们并没有期望你能够手写 XML Schema 和 WSDL。 除此之外，这都是底层建筑。你无需关注它。</p>
<p>开：哇哦，等等，那个词是什么？胃死兜？</p>
<p>S达：哦，我没有提过 WSDL？W-S-D-L。Web Services Description Language（Web 服务描述语言）。它是关于你如何定义数据类型、参数列表、操作名称、传输绑定和端点 URI 的，这样客户端开发者就可一访问你的服务。了解一下吧。</p>
<p>开：（阅读 WSDL 说明书）我相信编写这个的那个家伙已经被干掉了。这个甚至在内部都不一致。而且 HTTP GET 绑定做了什么。我想 GET 并没有定义。</p>
<p>S达：别担心那个。没人用那个。无论如何，你的工具会生成 WSDL，而在 WSDL 里会有 schema。</p>
<p>开：但是没有其他办法绕过去吗？难道不应该是我先设计好约束条件，然后生成代码吗？</p>
<p>S达: 好吧，当然，我想这听起来在原则上是对的。但这并不容易做到，而几乎没有 SOAP 栈支持先进行 WSDL 的开发。只让工具来承担这些好了。</p>
<p>开：还有一个问题。如果现在传递一个 XML Schema 兼容的消息，在哪可以指定操作名称？</p>
<p>S达：好吧，还记得 SOAPAction HTTP 头部吗？大多数人将其放到了这里。</p>
<p>开：大多数人？</p>
<p>S达：好吧，这个新模式实际上还没有在任何地方使用。</p>
<p>开：我同时注意到你们整个行业都建立在模棱两可之上的，有时有错误，还有一些定义的说明不是那么标准。事实上，SOAP 和 WSDL 说明书都还只是 W3C 记录，连工作草案都算不上。</p>
<p>S达：我们正在为此努力。</p>
<p>开：这能给我提供我之前所承诺过的互通性吗？</p>
<p>S达：当然。</p>
<p>开：我尝试一下。</p>
<p>（时间飞逝……）</p>
<p>开：现在变得丑陋了。我搭档的工具不能处理我的工具生成的 WSDL。不仅如此，它生成的 schema 是令人费解而且不可重用的。并且看起来没有工具认同如何处理 SOAPAction 头部是最佳的。</p>
<p>S达：听到这个真遗憾，伙计。从好的地方着想，没人再用 Doc/Lit 模式了。为了让无依赖传输回来，现在我们全都使用了 wrapped-doc/lit。这听起来很酷吧：wrapped-doc/lit？</p>
<p>开：这是什么？</p>
<p>S达：好吧，这和 Doc/Lit 类似，只是你取得整个消息并且将其包裹到有着相同名字的元素中作为操作。这样操作名称就回到消息中它应该在的地方。</p>
<p>开：好的，关于这些的说明在哪里？</p>
<p>S达：哦，这个没有说明。只是微软这么做而已。看起来是个不错的主意，所以现在所有酷毙了的小子们都这么做。然而，有一个关于此的新东西。我想你可能会喜欢它。称为 Web 服务互通性小组，或者叫做 WS-I。他们要做的工作就是从 SOAP 和 WSDL 说明书中移除那些模凌两可的东西。我知道你相当中意说明书。</p>
<p>开：所以，换句话说，这个说明书糟糕到你们需要一个标准化实体来对标准进行标准化。天啊。好吧，这能解决我的互通性问题吗？</p>
<p>S达：哦，当然。只要你使用 WS-I 兼容的 SOAP 栈，避免使用 8/10ths 的 XML Schema，不要使用任何不寻常的数据类型，并且不要按照 WebSphere 和 Apache Axis 来工作。</p>
<p>开：那么就使用 wrapped-doc/lit 来解释它？</p>
<p>S达：呃，不。不过也没问题。你的工具明白它（有些心虚）。大多数情况下，不管怎么说。</p>
<p>开：让我总结一下。SOAP 的定义总是在不断变化，不管怎么样 SOAP 是简单的，并且不再意味着对象访问——虽然这是工具仍然在做的事情。</p>
<p>S达：差不多是这样，但是我们总是带领着你在这条路上前进。我们已经抨击过 SOAP 缩写的含义了。</p>
<p>开：真的！那么它现在到底什么意思啊？</p>
<p>S达：什么意思都没有。</p>
<p>开： （眨巴着大眼睛）</p>
<p>S达：让我告诉你关于 UDDI 吧。</p>
<p>&#8212;&#8212;&#8212;-翻译分割线&#8212;&#8212;&#8212;-</p>
<p>现在知道 REST 和 json 的魅力了吧？那些坚持使用 SOAP 的同学们，得有一种什么样的探索精神啊！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2011/11/s%e4%bb%a3%e8%a1%a8%e7%9d%80simple/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>When in Golang, do as the Gophers do.</title>
		<link>http://www.mikespook.com/2011/10/when-in-golang-do-as-the-gophers-do/</link>
		<comments>http://www.mikespook.com/2011/10/when-in-golang-do-as-the-gophers-do/#comments</comments>
		<pubDate>Sat, 22 Oct 2011 07:22:05 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[Golang]]></category>
		<category><![CDATA[golang]]></category>
		<category><![CDATA[gopher]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/?p=1142</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
前两天在某 golang 的 QQ 群里，有人对 channel 批判了一番。当时我就很想送他一副图，两句话。

When in Rome, do as the Romans do.

When in Golang, do as the Gophers do.

<span class="readmore"><a href="http://www.mikespook.com/2011/10/when-in-golang-do-as-the-gophers-do/" title="When in Golang, do as the Gophers do.">阅读全文——共178字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p><a href="http://www.mikespook.com/wp-content/uploads/2011/10/gopher.png"><img src="http://www.mikespook.com/wp-content/uploads/2011/10/gopher-179x300.png" alt="" title="gopher" width="179" height="300" class="alignleft size-medium wp-image-1143" /></a></p>
<p>前两天在某 golang 的 QQ 群里，有人对 channel 批判了一番。当时我就很想送他一副图，两句话。</p>
<p><strong>When in Rome, do as the Romans do.<br />
When in Golang, do as the Gophers do.</strong></p>
<p>这本是为了参加 ECUG 2011 Con. 的幻灯片里制作的一副图。<br />
自己感觉很满意。能体现使用 golang 的方法的核心思想。</p>
<p>分享出来，大家开心一下吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2011/10/when-in-golang-do-as-the-gophers-do/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>[翻译]Dennis Ritchie：Steve Jobs 的巨人肩膀</title>
		<link>http://www.mikespook.com/2011/10/dennis-ritchie-steve-jobs/</link>
		<comments>http://www.mikespook.com/2011/10/dennis-ritchie-steve-jobs/#comments</comments>
		<pubDate>Wed, 19 Oct 2011 08:59:50 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[My life]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[c programming language]]></category>
		<category><![CDATA[dennis ritchie]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[rob pike]]></category>
		<category><![CDATA[steve jobs]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/?p=1118</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
原文来自：http://www.wired.com/wiredenterprise/2011/10/thedennisritchieeffect/。

Jobs 和 dmr 老爹前后离开，让很多人不能不将其放在一起谈论。无论如何，他们都是伟大的人。有的时候在很短的时间里，这个世界同时失去两个伟大的人，是一件很难言语的事情。

“If I have seen further it is only by standing on the shoulders of giants.”- Isaac Newton.

<span class="readmore"><a href="http://www.mikespook.com/2011/10/dennis-ritchie-steve-jobs/" title="[翻译]Dennis Ritchie：Steve Jobs 的巨人肩膀">阅读全文——共3333字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>原文来自：<a href="http://www.wired.com/wiredenterprise/2011/10/thedennisritchieeffect/" title="Dennis Ritchie: The Shoulders Steve Jobs Stood On" target="_blank">http://www.wired.com/wiredenterprise/2011/10/thedennisritchieeffect/</a>。</p>
<p>Jobs 和 dmr 老爹前后离开，让很多人不能不将其放在一起谈论。无论如何，他们都是伟大的人。有的时候在很短的时间里，这个世界同时失去两个伟大的人，是一件很难言语的事情。</p>
<p>“If I have seen further it is only by standing on the shoulders of giants.”- Isaac Newton.</p>
<p>仅以此向 dmr 老爹致敬。</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;翻译分割线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<h1>Dennis Ritchie：Steve Jobs 的巨人肩膀</h1>
<p><a href="http://www.wired.com/wiredenterprise/author/cade_metz/" target="_blank">Cade Metz</a>撰写 2011十月13日 7:14 pm</p>
<p><a href="http://www.mikespook.com/wp-content/uploads/2011/10/thompson-and-ritchie.jpg"><img src="http://www.mikespook.com/wp-content/uploads/2011/10/thompson-and-ritchie-300x240.jpg" alt="" title="Dennis Ritchie (standing) and Ken Thompson at a PDP-11 in 1972. (Photo: Courtesy of Bell Labs)" width="300" height="240" class="alignleft size-medium wp-image-1119" /></a></p>
<p>对 Dennis Ritchie 的悼念完全不能同 Steve Jobs 去世后在 Web 上纷飞的如潮水般的赞美相提并论。但是他们确实如此。</p>
<p>甚至更夸张一些。</p>
<p>“当 Steve Jobs 上周去世后，产生了声势浩大的哀悼活动，而这是另人感动和恰当的。虽然 Dennis 有着更大的成就，但是公众甚至不知道他是谁。”另一个<a href="http://www.theregister.co.uk/2011/05/05/google_go/" target="_blank">程序界的传奇</a>，现在是一名 <a href="http://research.google.com/people/r/index.html" target="_blank">Google 人</a>，在著名的<a href="http://en.wikipedia.org/wiki/Bell_Labs" target="_blank">贝尔实验室</a>工作的20年里同 Ritchie 每日穿过同一个门廊的 Rob Pike 这样说到。<br />
<span id="more-1118"></span><br />
在周三的晚上，Pike 通过 <a href="http://plus.google.com/u/2/101960720994009339267/posts/ENuEDDYfvKP?hl=en" target="_blank">Google+ 上的一篇留言</a>公布了 Ritchie 与疾病进行了长久的斗争之后，在他新泽西的家中病逝的消息，尽管来自铁杆技术人的响应非常强烈，但整体上<a href="http://news.cnet.com/8301-1001_3-20119811-92/dennis-ritchie-father-of-c-programming-language-dies/?tag=mncol" target="_blank">来自 web</a> 的<a href="http://www.theregister.co.uk/2011/10/13/dennis_ritchie_obituary/" target="_blank">悼念</a>与 Ritchie 对现代社会广泛的影响并不匹配。Dennis Ritchie 是 C 语言之父，并且协同贝尔实验室科学家 Ken Thompson 一起，使用 C 构建了 UNIX，基于这个操作系统的构建是如此之多——包括 Steve Jobs 建立的 Apple 帝国。</p>
<p>“在 web 上几乎所有的事情都用到了这两个东西：C 和 UNIX，”Pike 告诉网友。“浏览器是用 C 编写的。UNIX 内核——几乎整个互联网都运行在其上——也是 C 编写的。web 服务器是 C 编写的，而如果不是用 C 编写的话，那就是用 Java 或者 C++，这些是 C 的衍生，或者 Python 或 Ruby，这些是用 C 实现的。以及所有运行这些程序的网络硬件，我几乎都可以断定是用 C 编写的。”</p>
<p>“现代信息经济是构建在 Dennis 之前所做的工作上，这一点也不夸张。”</p>
<p>他补充到，甚至 Windows 曾经也是用 C 编写的，以及 UNIX 的后继者包括 Apple 的桌面操作系统 Mac OS X，和运行在 iPhone 和 iPad 上的 iOS。“Jobs 是看得见的王，而 Ritchie 是无法看到的万王之王，”MIT 电器工程和计算机科学教授，计算机科学与人工智能实验室成员，Martin Rinard 这样说到。</p>
<p>“Jobs 的天赋在于他构建了那些人们真正喜欢使用的产品，因为他有品味并且可以让事情变得引人注目。Ritchie 构建的东西是技术方面的，可以用于构建核心的基础设施，人们几乎无法接触到，但是每天都在使用的东西。”</p>
<h2>从 B 到 C</h2>
<p>Dennis Ritchie 构建了 C，因为他和 Ken Thompson 需要一个更好的方法来构建 UNIX。最初的 UNIX 内核是用汇编语言编写的，但是很快他们决定他们需要一个“高级”语言，某些对数据来说可以提供更多的控制能力并且跨操作系统的东西。在整个1970年，他们尝试构建了第二代 Fortran，但是这个并不十分适合，然后 Ritchie 提议基于 Thompson 创造的叫做 B 的语言开发一个新的语言。</p>
<p>不论你相信哪个版本的传说，B 的命名来自 Thompson 的妻子 Bonnie 或者一个由剑桥在六十年代中期开发的语言 <a href="http://en.wikipedia.org/wiki/BCPL" target="_blank">BCPL</a>。在任何情况下，从 B 产生了 C。</p>
<p>B 是一种解释型语言——也就意味着它是运行在 CPU 上的软件的一种中间形态——但是 C 是编译型语言。它被翻译为机器码，然后这些机器码直接运行于 CPU 上。不过在那个时候，C 被认为是一个高级语言。它可以为 Ritchie 和 Thompson 提供所需的灵活性，与此同时它很快。</p>
<p><del datetime="2012-01-06T01:53:45+00:00">C 语言的第一个版本与现在我们知道的版本并不完全一样——不过还是有些类似的</del>C 语言的第一个版本和我们今天知道的并没有多少不同——尽管它当时还不成熟（thx @ye_hq）。它提供了完整的数据结构和“类型”用于定义变量，而这就是 Ritchie 和 Thompson 用于构建新的 UNIX 内核所使用的。“他们构建了 C 来编写程序，”在 10 年后加入贝尔实验室的 Pike 说到。“而他们要写的程序就是 UNIX 内核。”</p>
<p>Ritchie 的一个玩笑是 C 有着“汇编语言的力量和汇编语言的便利。”换句话说，他承认 C 不是一个绚丽夺目的发明，它仍然非常贴近硬件在运行。今天，它被认为是一个低级语言，而不是高级的。 然而 Ritchie 的玩笑对于这个新语言并不公平。通过提供真正的数据结构，它操作的层面已经足够高了。</p>
<p>“当你编写一个大程序的时候——而 UNIX 正是这种类型——就必须管理各种不同组件之间的相互影响：所有的用户，文件系统，磁盘，程序执行，以及使其能够有效的管理，你就需要能够对正在处理的信息有一个良好的表达。也就是我们所说的数据结构。”Pike 说到。</p>
<p>“在没有数据结构的情况下编写内核，并且使其向 UNIX 一样的保持一致和优雅是一个相当相当难的挑战。需要有一个方法将数据成组的放在一起，而在 Fortran 里是没有办法做到的。”</p>
<p>就当时而言，这样编写操作系统是非同寻常的，而这也使得 Ritchie 和 Thompson 最终设想移植操作系统到其他平台，他们在七十年代末期进行了这个工作。“这开启了 UNIX 运行在任何地方的水闸，”Pike 说到。“这全部都是 C 使其成为现实的。”</p>
<h2>Apple，Microsoft，和其超越者</h2>
<p>与此同时，C 在它自己的道路上越走越远，从贝尔实验室到世界上其他大学，以及 Microsoft，在二十世纪80年代爆发的软件公司。“使用 C 语言进行开发是一个巨大的进步，且和时宜… C 提供了正确的平衡性，使得可以在更高层面编写并更加产品化，但是当需要的时候，仍然可以控制到底如何处理，”NVIDIA 首席科学家和斯坦福的贝尔工程教授 Bill Dally 这样说到。“（它）加快了程序开发的步伐至少数十年。”</p>
<p>就像 Pike 指出的，Richie 在 C 中构建的数据结构甚至影响产生了现代语言如 C++ 和 Java 所使用的面向对象范型。</p>
<p>革命开始于 1973 年，Ritchie 发表了对语言的研究的论文，五年之后，他和同事 Brian Kernighan 发布了决定性的 C 书籍：C 程序设计语言。Kernighan 编写了这个语言初步的一些指南，然后同时他“扭着 Dennis 的胳膊”一起编写了一本书。</p>
<p>Pike 在多伦多大学就读的时候阅读了这本书，在有一天生病回家的下午拿起了它。“这个参考手册与其他手册相比是清晰和可读的典范。它无疑是优秀的。”他说。“我在病床上阅读了它，而它使我忘记了正在生病。”（译注：如果我说我是靠这本书过的 CET4 会不会有人相信？但是这是真的，它确实燃起了我对学习英语的渴望……）</p>
<p>就像许多大学生一样，Pike 已经在使用这个语言了。由于贝尔实验室捐赠了 UNIX 的代码，使得它风靡于大学校园。特别要提到的是，操作系统开始进入现代开源运动中了。 Pike 在讲述的时候，没有也无法夸大 Ritchie 的工作的影响力，因此即使 Ritchie 在 1983 年获得图灵奖，并且在 1998 年获得美国国家技术奖， 他得到的赞誉仍然无法匹及他的贡献。</p>
<p>如同 Kernighan 和 Pike 说得那样，Ritchie 本人是非同寻常的孤僻。“我与他在同一个屋檐下一起工作了超过 20 年，而我感觉我并不全部了解他，”Pike 这样说。但是这并不能解释为他行事低调。Steve Jobs 是一个孤僻的人，但是他在隐私方面的坚持成为了公众对他个人生活探索的动力。</p>
<p>Ritchie 在与众不同的时间生活，并且在与众不同的环境工作，在这点上他超过了任何人，例如 Jobs。他没有获得应得的这绝对没错。但是那些真正在意的人，都能明白他留下的跨时代的标志。“在牛顿关于站在巨人的肩膀上有一个标准，”Kernighan 说到，“我们都站在 Dennis 的肩膀上。”</p>
<p>附加的内容由 Jon Stokes 撰写。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2011/10/dennis-ritchie-steve-jobs/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>R.I.P. dmr</title>
		<link>http://www.mikespook.com/2011/10/r-i-p-dmr/</link>
		<comments>http://www.mikespook.com/2011/10/r-i-p-dmr/#comments</comments>
		<pubDate>Thu, 13 Oct 2011 05:32:20 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[My life]]></category>
		<category><![CDATA[dmr]]></category>
		<category><![CDATA[R.I.P.]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/?p=1106</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
在 Google Plus 上看到这个消息，淡淡的，有一些悲伤。上帝难道要学习C语言，并将天堂的系统换成UNIX的了么？



本想写点什么纪念一下，但是突然觉得对于这位神来说任何文字都显得苍白无力。

<span class="readmore"><a href="http://www.mikespook.com/2011/10/r-i-p-dmr/" title="R.I.P. dmr">阅读全文——共202字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>在 Google Plus 上看到这个消息，淡淡的，有一些悲伤。上帝难道要学习C语言，并将天堂的系统换成UNIX的了么？</p>
<p style="text-align: center;"><a href="http://www.mikespook.com/wp-content/uploads/2011/10/rob-pike-gplus.png"><img class="size-medium wp-image-1110 aligncenter" title="rob-pike-gplus" src="http://www.mikespook.com/wp-content/uploads/2011/10/rob-pike-gplus.png" alt="" /></a></p>
<p>本想写点什么纪念一下，但是突然觉得对于这位神来说任何文字都显得苍白无力。</p>
<p style="text-align: center;"><img class="aligncenter" title="Dennis Ritchie" src="http://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Dennis_MacAlistair_Ritchie_.jpg/225px-Dennis_MacAlistair_Ritchie_.jpg" alt="" width="225" height="260" /></p>
<p>虽然他说“I am not now, nor have I ever been, a member of the demigodic party.”但真的神终究是真的神。</p>
<p>R.I.P. dmr! We will miss you, Dennis Ritchie.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2011/10/r-i-p-dmr/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

