[转载]皇帝的旧衣

【原题】The Emperor’s Old Clothes

【译题】皇帝的旧衣

【作者】 C.A.R. Hoare

我在这次演讲(译注:指1980年图灵奖演讲)中首先和最愉快的任务向计算机器协会表达我深深的敬意,因为他们给了我极大的荣誉有机会去就自己所选的主题进行演讲。一个选择是多么难啊!我的科学成就,这个奖项予以了丰裕的体现,已经在科学文献中作了充分的描述。取代重复我职业的抽象学术,我更愿意非正式的谈谈我自己,我的职业经历,我的希望与恐惧,我审慎的成功,以及我相当程度上更少审慎的失败。较之“可以从一本科学性文献的印刷中所揭示的(can ever be revealed in the cold print of a scientific article)”,我从自己的失败中学到了更多东西,现在我也愿意让你们从我的失败中来学习。除此以外,失败在事后听来是很有趣的;虽然当时没那么有趣。 Continue reading

golang一些测试代码

[golang]package main

import (
"fmt"
)

func main() {
a := [5][4]int{
{1: 1},
{}, {}, {3: 1}}

fmt.Println(a)
}

[/golang]
[golang]package main

import (
"fmt"
)

func main() {
m := make(map[[2]interface{}]string)
key := [2]interface{}{}
m[key] = "value"
fmt.Println(m) // map[[<nil> <nil>]:value]
}
[/golang]

golang的tips和问题列表

golang newbie tips:

  • 空slice和nil的slice不相等
  • 对短的slice copy长的slice,不会报错,但是会被截断
  • a := [20]int{19: 1} 索引初始化,arr := [...]string{1: “ss”, 90: “90″} 这样都行?!
  • slice只能和nil判断是否相等,array和array比较应该长度和类型相同,就可以比较
  • unsafe.Sizeof([100]int64{}) == 800
  • 允许c, a, b = b, a, c这样的交换赋值
  • map不初始化的时候nil,不能进行操作,可以通过ret, ok := m[0]来判断是否成功,不成功的时候ret是初始化默认值,但是打印出来还是map[]很奇怪,多维数组一样,也可以通过ret, ok := xxx[i][j]来判断,那如果ok是false怎么make呢?
  • map只能用可以做等号比较的值作为key
  • map的for range可以for k, v := range m也可以for k := range m 同理slice也是
  • len可以用在map上,map也可以这样声明时初始化:m0 := map[int]string{1: “”, 2: “”}
  • make slice的时候和make map的时候,后面两个参数的意思,就是如何分配长度
  • 函数不支持嵌套,不支持重载和默认参数,但是支持可变参数列表
  • 声明的private小写函数没有使用不会编译错误?
  • 函数传入变长同类型参数时,只能作为最后一个参数,内部得到一个slice,内容是值拷贝得到的
  • fallthrough
  • string([]byte)
  • sizeof(struct{}) – (type xx int和type xx struct)

golang待尝试的问题:

  • slice和数组的转换,数组的copy问题(待实践)
  • new出来的slice指针的意义和可用性(无闻讲座slice节的5分左右)(猜想:你想到的,go都考虑到了)
  • len和cap能不能分别用在数组和slice(猜想:cap不能用在数组,len都可以用)
  • select{}死锁的原理,和select用法(待实践)
  • array的new,make等可用性(猜想:你想到的,go都考虑到了)
  • nil的slice的append(猜想:可以进行,底层进行了特殊处理)(已验证,猜得对)
  • capacity充裕的slice进行append以后,老slice的修改是否会引起新slice对应位置的更改(猜想:是)(已验证,果断影响了)
  • 通过通信来共享内存,而不是通过共享内存来通信,那通信的性能如何
  • 匿名结构体声明marshal和unmarshal

golang的slice传参

golang slice传参的坑
源自对这个的解读:http://my.oschina.net/chai2010/blog/161384
自己写了几行挖坑的代码

[go]package main

import (
"fmt"
)

func myAppend(s []interface{}) {
s = append(s, nil)
}

func test(capacity int) {
old_s := make([]interface{}, 0, capacity)
fmt.Println("old_s : ", old_s)
new_s := append(old_s, 100)
myAppend(old_s)
fmt.Println("old_s : ", old_s)
fmt.Println("new_s : ", new_s)
}

func main() {
test(0)
test(100)
}
[/go]

$ go run slice_bug.go
old_s : []
old_s : []
new_s : [100]
old_s : []
old_s : []
new_s : [<nil>]

可以看到,capacity是100的时候,append后由于有内存,所以地址没有改变,所以后来append的nil把之前的100替换掉了,而capacity是0的时候,本来就是换了一个地址,就不会出现这样的问题。

所以,go传参其实都是传值,进一步看unsafe.SizeOf的话,一个slice只有24字节的空间,内部包含了数组的指针。

这真的是一个坑,我觉得解决方式是传slice的指针,或者像无闻老师说的,使用slice做函数返回值才靠谱(但是他说一般返回值不会很大,其实是一个结构体,也就是定值:24字节)。

C和C++如果当时学好了真心给力,一下子就能明白,省得去瞎猜。

golang内置类型和函数

内置类型

值类型:
bool
int(32 or 64), int8, int16, int32, int64
uint(32 or 64), uint8(byte), uint16, uint32, uint64
float32, float64
string
complex64, complex128
array — 固定长度的数组

引用类型:(指针类型)
slice — 序列数组(最常用)
map — 映射
chan — 管道

内置函数
append — 把东西增加到slice里面,返回修改后的slice
close — 关闭channel
delete — 从map中删除key对应的value
panic — 停止常规的goroutine
recover — 允许程序定义goroutine的panic动作
imag — 返回complex的实部
real — 返回complex的虚部
make — 返回Type本身(只能应用于slice, map, channel)
new — 返回指向Type的指针
cap — 容量,容积capacity
copy — 复制slice,返回复制的数目
len — 返回长度

内置接口error

type error interface { //只要实现了Error()函数,返回值为String的都实现了err接口
Error() String
}

Raspberry PI 刷机后配置步骤自用速成笔记

忘记密码:
init=/bin/sh
mount -rw -o remount /
passwd pi
sync
exec /sbin/init

一些link:

  • 树莓派系统监控web界面:http://vanhaarst.net/
  • web监控源码:https://gist.github.com/jvhaarst/4388108
  • 开机email提醒当前ip地址脚本:http://1.alive.sinaapp.com/raspberry_init_email.py

一些刷机后bootstrap步骤:

  • /boot/config.txt取消注释hdmi_force_hotplug=1,并且hdmi_drive=2,让hdmi转接口强制输出信号
  • 可以考虑系统刷到U盘,然后调整/boot/cmdline.txt是/dev/sda2即可启动,但是需要手动expand fs
  • raspi-config调整expend filesystem,修改密码,修改domain,修改键盘(通用的101键PC键盘,其他,English US international alternate),locale,timezone等等
  • 装vim
  • 换源 /etc/apt/sources.list
  • /etc/vim/vimrc取消syntax on前面的注释
  • /etc/rc.local配置开机发送邮件的脚本
  • 卸载不用的垃圾包
  • apt-get dist-upgrade
  • 装常用包
  • apt-get autoremove
  • 余下配置

以下是一些tips:

  • raspi-config调整expend filesystem,修改密码,修改domain,修改键盘,locale,timezone等等
  • 查看传感器温度 (来自:http://www.raspberrypi.org/phpBB3/viewtopic.php?f=26&t=34994)
    cat /sys/class/thermal/thermal_zone0/temp或者 /opt/vc/bin/vcgencmd measure_temp
  • 查看CPU当前频率
    cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
  • 切换到最快的源(中科大的)
    deb http://mirrors.ustc.edu.cn/raspbian/raspbian/ wheezy main contrib non-free rpi
  • 卸载用不到的包
    sudo apt-get purge scratch squeak-vm python3.2 python3.2-minimal dillo netsurf-common netsurf-gtk midori wpagui wpasupplicant sonic-pi
  • 安装常用包
    sudo apt-get install xrdp subversion hdparm ipython screen chromium chromium-l10n  chromium-browser chromium-browser-l10n
  • 自动提示软件包~sudo apt-get install command-not-found sudo update-command-not-found
  • Server相关
    sudo apt-get install nginx golang php5

Amazon EC2/Ubuntu系统下搭建VPN环境

# eggfly: 1723 port
以下是基于Amazon EC2/Ubuntu搭建PPTPD服务提供VPN连接的过程记录。至于为什么要搞VPN,大家都懂的。。。而我主要是要访问Python的一些网站以及使用我非常喜欢的Google docs。

PPTP采用TCP 1723端口,因此在Amazon EC2的防火墙配置中,必须打开这个端口,否则client端无法接入。(网上有文章说也需要打开47端口(GRE端口),我在Amazon EC2上试验的结论是不需要特别设置。)

step1: 安装pptpd

很简单的命令:sudo apt-get install pptpd

step2: 修改pptpd的配置

有三个文件需要修改:

(1)修改/etc/pptpd.conf,添加以下内容(原文件中可能已经有这些内容,确认即可)

localip 192.168.0.1

remoteip 192.168.0.100-110

# (Recommended)

# localip 192.168.0.1
# remoteip 192.168.0.234-238,192.168.0.245

localip是指VPN建立后,client可以用这个地址访问VPN server。

remoteip就是指分配给client的地址。

(2)修改/etc/ppp/pptpd-options文件,增加以下内容:

ms-dns 8.8.8.8

ms-dns 8.8.4.4

这个配置是使用Google的DNS解析。至于原因,你也懂的。。。

(3)修改/etc/ppp/chap-secrets文件,设置客户机登录的帐号和密码:

# client server secret IP addresses

yxh * 1234 *

“client”是用户名,“server”是服务器地址,”secret”是登录密码,”IP addresses”是分配的地址,如果指定*,则由系统自动分配。

step3: 重起PPTPD服务:sudo service pptpd restart

step4:配置IP转发

修改/etc/sysctl.conf文件,打开以下的注释:

net.ipv4.ip_forward=1

step5: 重新加载IP转发配置

sudo sysctl -p

step6: 修改Iptables,设置网络地址翻译

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

上述设置在重起后悔丢失,因此需要修改 /etc/rc.local文件, 在exit 0之前添加以下语句:

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

step7: 配置DDNS

Amazon EC2每次重起都会变换地址,因此我们需要配置DDNS来获取动态域名解析。在这一步之前,需要在DynDNS上申请一个免费的域名。国内类似的服务商是“花生壳”,我没有进行过测试,不知道“花生壳”是否也适合以下配置。

申请到DynDNS帐号后,下载并安装ddclient:

sudo apt-get install ddclient

安装过程中, 会有简单的界面进行配置, 设置dyndns的相关帐户即可。设置完成后, 配置信息会自动写入/etc/ddclient.conf文件。

完成上述步骤后,就可以在windows客户端拨号建立VPN连接了。

以上资料主要参考一篇国外有人的blog:http://www.dikant.de/2010/10/08/setting-up-a-vpn-server-on-amazon-ec2/

最后说一下Amazon EC2。国内有几篇很不错的翻译可以参考,不过最好的资料还是Amazon本身提供的GettingStarted文档,虽然是英文的,不过非常简单明了:http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide

SQLite Slogan

感谢网络,感谢开源与共享。

这是SQLite的作者送给免费使用SQLite的人的祝福(blessing),程序员做到这份儿上,不得不让人敬佩。

May you do good and not evil. 愿你众善奉行,诸恶莫作
May you find forgiveness for yourself and forgive others. 愿你宽容自己及他人
May you share freely, never taking more than you give. 愿你乐于与人分享,绝不索取多于付出