Big Chimpin!
Avatar

Bian Jiang

Vcard Download vCard   what is this?
Rss_icon

Recent Activity


Filter by:
All
  • Speech Synthesis & Analysis Software For Linux Speech Synthesis & Analysis Software For Linux
  • iPhone 4 Teardown - iFixit iPhone4拆机过程
  • 99%的人都不知道手机的隐藏功能

    1、当不喜欢别人打搅自己的时候,又不想关机,给大家一个办法,使自己的号码变成空号。
    输入 **21*999999# ,按打电话时候的拨出键 。当别人拨打你的电话时候就你的号码就变成空号了。
    再输入 ##21#,在按拨出键 又正常了。
    PS:这个功能移动公司是不收费的,应该是手机号码的一个漏洞。可以当场实验,如果觉得好用就转给你好友,以后不想接听那个令你伤心的她/或他的电话的时候,就用得到了。

    2、 识别手机质量的好坏
    先按*#06#,然后在你的手机上会出现一个序列号给你,你就数到第七个和第八个数。
    假如你的第七个和第八个数是下面对应的两个数,那么你的手机质量的好坏就确定了。
    0,2 or 2,0,是很差的手机
    0,8 or 8,0,是好一点儿的手机
    0,1 or 1,0,是非常好的手机
    0,0 代表是原产公司生产的,是质量最好的手机(原装手机)
    1,3 代表是阿赛拜疆生产的,是非常非常差的手机

    3、隐形的备用电池
    你的手机电量不足了,为了让它能够继续使用,按*3370#键,手机会重新启动,启动完毕后,你就会发现电量增加了50%。这部分隐藏的备用电量用完了你就必须得充电了,再次充电的时候,隐形的备用电池也同时充电,下次电量低的时候又可以用这个方法。知道这个在紧急情况下如果手机电量不足非常管用。

    4、车用遥控器落在车里了?
    你的车用遥控能打开吧?如果可以,在你有一天将车用遥控器落在车里而且备用的遥控又在家里的话,你会发现有个手机真方便,用手机拨通家里人的手机,将你的手机拿在离车门一英尺的地方,同时家里人拿着遥控器在他的手机旁边按响遥控器上的开锁键,这边你的车门就可以打开了。这个方法不管你把车开得离家有多远都奏效。 (SEVEN亲身试过了,很有效,很神奇哦)

    5、紧急情况
    全世界的手机都可以拨打的共同紧急救援号码是112,加入你发现自己所在的地区无手机信号覆盖,同时你又遇到了紧急状况,用你的手机拨打112准没错,因为这时候你的手机会自动搜索所有可用的网络并建立起紧急呼叫。特别有趣的是,即使你的手机是在键盘锁定的状态,你同样可以拨打112。试试吧!

    6、手机被偷了?
    有个办法让小偷也用不了,嘿嘿!查看手机的序列号,只需键入* # 0 6 #, 15位序列号会出现在手机屏幕上,全世界的每一台手机都有一个独一无二的序列号,把这个序列号记录下来并保存好。有一天如果你的手机不幸被偷了,打电话给手机提供商,并提供你的手机序列号,他们会帮你把手机屏蔽,这样即使小偷换了SIM卡,仍然无法使用,你的手机对小偷来说变得一无是处。如果全世界每个手机持有者都这么做,那么偷手机就没有意义了。在澳洲,警方甚至建立了一个被盗手机数据库,如果你的手机被找到了,就可以归还给你了。

    7、手机电池不要等到没电才充电。
    一般我们都会有一种想法就是手机的电池电力要全部放完再充电比较好基本上是没错的,因为我们在以前使用的充电电池大部分是镍氢(NiH)电池,而镍氢电池有所谓的记忆效应若不放完电再充的话会导致电池寿命急速减少。因此我们才会用到最后一滴电才开始充电。但现在的手机及一般IA产品大部分都用锂(Li)电池,而锂电池的话就没有记忆效应的问题。若大家还是等到全部用完电后再充的话反而会使得锂电池内部的化学物质无法反应而寿命减少。最好的方法就是没事就充电让它随时随地保持最佳满格状态,这样你的电池就可用的又长又久喔。这是从厂商那得到的讯息,并经过本身测试而得。

    8、当手机正在充电时,请勿接电话!!
    原因是手机在充电时,来电接听的话会有潜在的危险。印度有一个31岁在保险公司任职业务经理的年轻人,十几天前在手机还接着充电器的时候接听电话,过了几秒大量的电流经过手机,这个年轻人被摔落到地面,家人发现时,手指烧伤,心跳微弱,并且已经失去意识。经紧急送到医院后,医生宣布到院死亡。行动电话是目前大家最常使用的现代发明。然而,我们也必须要警觉到仪器致死的危险。

    9、手机剩一格时不要使用
    收讯满格与只剩一格时相比,发射强度竟然相差1000倍以上.所以……常讲手机的人……要注意哦……^0^、昨天从一位手机商那儿获得一项很重要的讯息,那就是当你发现手机的收讯强度只剩下一格的时候,宁可挂断不谈或者是改用公用电话.千万不要再滔滔不绝、口沫横飞、浓情蜜意、欲罢不能、没完没了…为什幺呢?大家都知道手机的电磁波一直是让人担心的问题.而手机的设计为了在收讯较差的地区仍能保有相当的通话质量,会加强手机的电磁波发射强度.当收讯满格与只剩一格时相比,发射强度竟然相差1000倍以上.电磁波强度高达0.6W(瓦特).0.6W究竟有多强呢?我无法具体描述它对你的脑袋会有什幺不良影响,但可以换成两个例子来比较:

    1)把喇叭直径约4公分左右的小型收音机音量开到最大然后贴在耳朵上,那样的噪音能量一般为0.25W,不到0.5W。   2)把手指头放在输出强度0.1W的雷射光前面(相当于光纤网络的?D干线能量)几秒钟内你会有灼痛的感觉,你能长时间忍受上述这两种状况吗? 那你又如何确认0.6W的电磁波紧贴在你的耳朵上会没事呢?

    10.12593+电话号码=陷阱
    你是不是把外地朋友的电话用17951+电话号码的格式储存在电话号码本里?而不是单独拨?那么收费就会从0.39元每分钟变成1.3元每分钟.我也向 1860查询过了他们的解释是如果储存在电话号码本里?系统将无法识别。所以无法获得资费优惠,必须每次在键盘上直接按12xxx。神州行用户如此?动感地带用户,全球通也一样。如果你是一个中国移动用户,当你知道中国移动为你设置以下的陷阱的时候,便不再惊讶于你的话费为何会像长了翅膀一样的飞走。用 12593+电话号码可以优惠,但如果你预先将“12593+电话号码“存在手机的电话本,使用的时候调出来然后拔打出去,这时中国移动不承认你使用了 12593这种优惠的拔打方式,而按照直接拔打的方式计费。如果你是在漫游,两种计费方式可以相差7倍之多!当我得知如此计费之后,我真的不知如何表达我的愤怒,后来打10086咨询时,如果不是主动冶询问这个问题,工号为6608的小姐根本就不告诉我这样的计费。

    11、手机费的寄生虫
    手机莫名其妙定置了无用短信,强烈建议大家都看一下自己有没有中招,最简单方法退订每月偷你手机费的寄生虫!中国移动在3.15被迫推出一项新业务,如果您是中国移动的手机用户,键入数字“0000“,发送短信至10086,数秒钟内将自动回复一条短信列表,显示您的手机上究竟订制了哪些短信服务,究竟是哪些短信服务商明着、暗着每月扣除您的手机费;键入数字“00000“,发送短信至186201,即可退订所有短信服务。

    12、不要赶着凑正好1分钟
    我们打电话的时候常常会为了正好赶在1:00前结束而庆幸,但其实并不是这样的,据一位中国移动的工作人员说,其实在你通话到0:55的时候就已经算一分钟了,所以0:55~1:00的通话时间其实是算你2分钟的钱~

    13、手机一进水,
    请切记不要作任何按键动作,尤其是关机(一按任何动作,水马上会跟着电路板流串),正确的方法为马上打开外盖,直接将电池拿下,直接强迫断电,可保主机板不被水侵袭。这个常识非常重要,故转告各位,使大家的手机可用久一点。学一学吧!以后以备不时之需啊!

    14、如何让手机电池起死回生
    当你的行动电话电池使用时间变短(记忆效应或老化)时,你是否会再买一颗电池来更换呢?下次当你碰到这种情况时请省下你的钱,告诉你一个很有效的方法不妨试试看:
    1)把电池用报纸包起来再放进塑料袋裹包好放入冷冻库三天(报纸可吸收多余水份)
    2)三天后取出常温下放二天
    3)二天后将电池充电,充饱后装进行动电话裹测试(预估可救回80%-90%)

    15、给你的手机做个CPR吧!
    手机是否常断电?或是明明充饱了电没多久就又没电了?一定怀疑过是不是手机的寿命终了?别担心,它只是一时“心跳停止”,只要一块小小的橡皮擦就能起死回生了!把电池取出后用橡皮擦把电池上的接点(黄铜片)擦干净,再装回手机上,你会发现真是太神奇了!它竟然活过来了!还像颗新的呢!真的很有用,提供大家做参考!
    16、教你如何消除手机屏幕刮痕
    大家是否常常会遇到手机屏幕有刮痕而不知如何处理的情况呢?告诉大家一个好用的秘方....(前几天在电视上看到的) 把牙膏适量挤在湿抹布上后用力在手机屏幕刮伤处前后左右来回用力涂匀..... 你将发现.....手机的屏幕刮痕会因此而消失....很神奇吧...!! 更神奇的事....在用干净的抹布或卫生纸擦干净后..手机屏幕还会变得更亮哦....
    台大化学教授表示:原理为牙膏它只是刷牙的辅助用品,具有磨擦作用(修补作用) 和去除菌斑,清洁抛光牙面,因此使用在手机屏幕上面会有同样的效果

    如果您的阅读器看不到视频,请移步原文链接: http://ta.md/703/
    人人都是艺术家 Copyright © 2010 - 2012 分享国内外精彩网事。
    更多精彩欢迎您订阅 http://feeds.feedburner.com/tamd,欢迎网友投稿推荐文章。
    广告一则: .me 域名全国最低价,首年仅需40元,续费130元促销中! )

  • New Talk and Tutorials

    Rob Pike recently gave a talk at Stanford's Computer Systems Colloquium (EE380). Titled "Another Go at Language Design", the presentation gives an overview of the itches Go was built to scratch, and how Go addresses those problems. You can view a video stream of the talk, and download the slides.

    Last week's release included a code lab, "Writing Web Applications," that details the construction of a simple wiki program. It is a practical introduction to some fundamental Go concepts, and the first of a series of Go code labs.

    Lastly, we are often asked "How do Go packages work?" It's easier to show than to explain, so I put together a Go Packages screen cast that demonstrates the process of writing, building, installing, and redistributing Go packages. I hope to post more of these covering a variety of Go programming topics to the gocoding YouTube channel in the near future.

  • 人民是靠不住的,军警也是靠不住的

    作者:涂子方 | 评论(6) | 标签:时事, 社会, 政治, 民情

    虽然说“枪杆子里面出政权”,但有时候也有例外,而且这种例外在现代社会似乎越来越多。

    官媒中新社北京4月8日电,吉尔吉斯斯坦共和国反对派领导人、前外长罗萨·奥坦巴耶娃8日宣布,她领导的反对派已经成立临时政府,接管国家政权。

    奥坦巴耶娃要求吉现任总统库尔曼别克·巴基耶夫辞职。她声称已经成立了一个由她本人负责的临时政府接管政权。她表示:“临时政府将接管半年,直到我们起草一份新宪法,并创造能够确保自由公正地选举领导人的环境。”

    昨晚另一官媒CCTV1的新闻联播对此消息的报道也很谨慎,电视中没有播出吉尔吉斯首都比什凯克近日发生的大规模群众骚乱场面,此前在报道伊朗总统选举发生的群众骚乱时也是如此。

    不知出于什么原因,中国官媒对全世界发生的大规模群众骚乱都谨慎报道,大概是有关部门怕这玩意儿像猪流感一样的会传染。

    而网上的视频、图片和港澳电视的报道就要客观得多:

    吉尔吉斯军警开枪射杀示威群众;

    血染街头、倒卧在地的死伤群众;

    奋不顾身的示威群众围抢军警的武器;

    落单的军警被群众按在地上拳打脚踢;

    夺枪了的群众向军警开火;

    政府办公大楼、总统府、国家电视台等要地被示威群众占领;

    建筑物、被推翻的汽车在烈火中熊熊燃烧;

    ……。

    最后的情况是,军警即使奉命开枪打死打伤了近千人,但还是没有将反对派群众的示威镇压下去,反而激起了更大规模的群众反抗,于是总统巴基耶夫逃到不知什么地方躲了起来,看来现政府垮台已成定局。

    巴基耶夫政府为何会垮台?估计咱官媒照例会宣传这是吉尔吉斯国内外敌对势力操纵的结果,也许是,人家国家的事情,谁知道呢。

    但毛主席教导我们说:“内因是变化的根据,外因是变化的条件,外因通过内因而起作用”。苍蝇不叮无缝的蛋,关键还是巴基耶夫集团自己的事情没有做好,不然吉尔吉斯的群众也不会冒着枪林弹雨,前赴后继的用生命和鲜血来被人家操纵。

    网上有报道说,去年年底,总统巴基耶夫的小儿子、32岁的马克西姆·巴基耶夫被任命为发展、投资和革新部部长,直接控制了该国的财政大权。吉政府从今年1月起大幅提高国内电力和供暖价格,其中电力价格几乎提高了2倍。与此同时,总统巴基耶夫开始推行政府结构和宪法改革,人们普遍认为,这些举措将强化总统权力,加剧独裁倾向。

    吉尔吉斯发生的事情告诫全世界所有的当政者:不要明目张胆的安排官二代担任要职;不要让物价飞涨;不要搞逆民意的体制改革。

    人民是靠不住的。

    军警也是靠不住的。

    涂子方的最新更新:
  • 要思考好制度是如何形成的 / 2010-04-08 12:44 / 评论数(1)
  • 总算有人说了真话 / 2010-04-07 11:19 / 评论数(4)
  • 由王家岭矿难所想到的 / 2010-04-06 11:00 / 评论数(6)
  • 慎终追远话清明 / 2010-04-05 12:39 / 评论数(0)
  • 好事不出门,坏事传千里 / 2010-04-04 11:42 / 评论数(8)
  • 为什么优秀开发者进入Google后就不参与开源了

    很多优秀的开发者在进入Google之前都是非常活跃的开源贡献者,但是进入Google之后往往就销声匿迹了,包括嘲笑了此现象的Memcached 作者Brad在进入Google之后也无法逃脱此规律。Brad在最近一篇文章Contributing to Open Source projects谈到相关原因

    • 许多优秀开发者都很喜欢编程,他们喜欢研究有趣有挑战的问题,并不特别在意这些项目是否开源。
    • 大家都太忙,Google似乎用尽了每个人的空余时间。并不是说Google强迫大家一天到晚都在干活,而是由于Google里面太多有趣的东西做了,Brad经常挂在口头一句话就是“现在手头有7个属于20%空余时间的项目”。
    • Google的开发环境太好了,源代码控制,build系统,code review工具,debugger调试工具,profiler调优工具,submit queues, continuous builds, test bots, 文档以及所有相关的自动化工具及流程非常完善。因此很容易hack任何项目,在任何地方,或者给任何人提交patch,并且值得一提的是,很容易找到对应的人或者list去提交patch。通常说来,提交patch是参与特性讨论,表达诚意的最好方式,即使你的patch是有问题的。

    从上面尤其是第3点来看,Google确实是技术人员的理想环境。

    Similar Posts:
  • Google Go:初级读本

    from http://www.infoq.com/cn/articles/google-go-primer

    作者 Samuel Tesla 译者 黄璜 发布于 2010年4月2日 上午12时5分

    Google最近发布新型的编程语言,Go。它被设计为将现代编程语言的先进 性带入到目前仍由C语言占统治地位的系统层面。然而,这一语言仍在试验阶段并在不断演变。

    Go语言的设计者计划设计一门简单、高效、安全和 并发的语言。这门语言简单到甚至不需要有一个符号表来进行词法分析。它可以快速地编译;整个工程的编译时间在秒以下的情况是常事。它具备垃圾回收功能,因 此从内存的角度是安全的。它进行静态类型检查,并且不允许强制类型转换,因而对于类型而言是安全的。同时语言还内建了强大的并发实现机制。

    阅读Go

    Go的语法传承了与C一样的风格。程序由函数组成,而函数体是一系列的语句序列。一段代码块用花括号括起来。这门语言保留有限的关键字。表达式使用 同样的中缀运算符。语法上并无 太多出奇之处。

    Go语言的作者在设计这一语言时坚持一个单一的指导原则:简单明了至上。一些新的语法构件提供了简明地表达一些约定俗成的概 念的方式,相较之下用C表达显得冗长。而其他方面则是针对几十年的使用所呈现出来的一些不合理的语言选择作出了改进。

    变量声明

    变量是如下声明的:

    var sum int // 简单声明
    var total int = 42 // 声明并初始化

    最值得注意的是,这些声明里的类型跟在变量名的后面。乍一看有点怪,但这更清晰明了。比如,以下面这个C片段来说:

    int* a, b;

    它并明了,但这里实际的意思是a是一个指针,但b不是。如果要将两者都声明为指针,必须要重复星号。然后在Go语言里,通过如下方式可以将两者都 声明为指针:

    var a, b *int

    如果一个变量初始化了,编译器通常能推断它的类型,所以程序员不必显式的敲出来:

    var label = "name"

    然而,在这种情况下var几乎显得是多余了。因此,Go的作者引入了一个新的运算符来 声明和初始化一个新的变量:

    name := "Samuel"

    条件语句

    Go语言当中的条件句与C当中所熟知的if-else构造一样,但条件不需要被打包在括号内。这样可以减少阅读代码时的视觉上的混乱。

    括号并不是唯一被移去的视觉干扰。在条件之间可以包括一个简单的语句,所以如下的代码:

    result := someFunc();
    if result > 0 {
    /* Do something */
    } else {
    /* Handle error */
    }

    可以被精简成:

    if result := someFunc(); result > 0 { 
    /* Do something */
    } else {
    /* Handle error */
    }

    然而,在后面这个例子当中,result只在条件块内部有效——而前者 中,它在整个包含它的上下文中都是可存取的。

    分支语句

    分支语句同样是似曾相识,但也有增强。像条件语句一样,它允许一个简单的语句位于分支的表达式之前。然而,他们相对于在C语言中的分支而言走得更远。

    首先,为了让分支跳转更简明,作了两个修改。情况可以是逗号分隔的列表,而fall-throuth也不再是默认的行为。

    因此,如下的C代码:

    int result;
    switch (byte) {
    case 'a':
    case 'b':
    {
    result = 1
    break
    }

    default:
    result = 0
    }

    在Go里就变成了这样:

    var result int
    switch byte {
    case 'a', 'b':
    result = 1
    default:
    result = 0
    }

    第二点,Go的分支跳转可以匹配比整数和字符更多的内容,任何有效的表达式都可以作为跳转语句值。只要它与分支条件的类型是一样的。

    因此如下的C代码:

    int result = calculate();
    if (result < 0) {
    /* negative */
    } else if (result > 0) {
    /* positive */
    } else {
    /* zero */
    }

    在Go里可以这样表达:

    switch result := calculate(); true {
    case result < 0:
    /* negative */
    case result > 0:
    /* positive */
    default:
    /* zero */
    }

    这些都是公共的约定俗成,比如如果分支值省略了,就是默认为真,所以上面的代码可以这样写:

    switch result := calculate(); {
    case result < 0:
    /* negative */
    case result > 0:
    /* positive */
    default:
    /* zero */
    }

    循环

    Go只有一个关键字用于引入循环。但它提供了除do-while外C语言当中所有可用的循环方式。

    条件

    for a > b { /* ... */ }

    初始,条件和步进

    for i := 0; i < 10; i++ { /* ... */ }

    范围

    range语句右边的表达式必须是arrayslicestring或者map, 或是指向array的指针,也可以是channel

    for i := range "hello" { /* ... */ }

    无限循环

    for { /* ever */ }

    函数

    声明函数的语法与C不同。就像变量声明一样,类型是在它们所描述的术语之后声明的。在C语言中:

    int add(int a, b) { return a + b }

    在Go里面是这样描述的:

    func add(a, b int) int { return a + b }

    多返回值

    在C语言当中常见的做法是保留一个返回值来表示错误(比如,read()返回0),或 者保留返回值来通知状态,并将传递存储结果的内存地址的指针。这容易产生了不安全的编程实践,因此在像Go语言这样有良好管理的语言中是不可行的。

    认识到这一问题的影响已超出了函数结果与错误通讯的简单需求的范畴,Go的作者们在语言中内建了函数返回多个值的能力。

    作为例子,这个函数将返回整数除法的两个部分:

    func divide(a, b int) (int, int) {
    quotient := a / b
    remainder := a % b
    return quotient, remainder
    }

    有了多个返回值,有良好的代码文档会更好&mdash;&mdash;而Go允许你给返回值命名,就像参数一样。你可以对这些返回的变量赋值,就像其它的变量一样。所以我们可以重写divide:

    func divide(a, b int) (quotient, remainder int) {
    quotient = a / b
    remainder = a % b
    return
    }

    多返回值的出现促进了"comma-ok"的模式。有可能失败的函数可以返回第二个布尔结果来表示成功。作为替代,也可以返回一个错误对象,因此像下面这样的代码也就不见怪了:

    if result, ok := moreMagic(); ok {
    /* Do something with result */
    }

    匿名函数

    有了垃圾收集器意味着为许多不同的特性敞开了大门&mdash;&mdash;其中就包括匿名函数。Go为声明匿名函数提供了简单的语法。像许多动态语言一样,这些函数在它们被定义的范围内创建了词法闭包。

    考虑如下的程序:

    func makeAdder(x int) (func(int) int) {
    return func(y int) int { return x + y }
    }

    func main() {
    add5 := makeAdder(5)
    add36 := makeAdder(36)
    fmt.Println("The answer:", add5(add36(1))) //=> The answer: 42
    }

    基本类型

    像C语言一样,Go提供了一系列的基本类型,常见的布尔,整数和浮点数类型都具备。它有一个Unicode的字符串类型和数组类型。同时该语言还引入了两 种新的类型:slicemap

    数组和切片

    Go语言当中的数组不是像C语言那样动态的。它们的大小是类型的一部分,在编译时就决定了。数组的索引还是使用的熟悉的C语法(如 a[i]),并且与C一样,索引是由0开始的。编译器提供了内建的功能在编译时求得一个数组的长度 (如 len(a))。如果试图超过数组界限写入,会产生一个运行时错误。

    Go还提供了切片(slices),作为数组的变形。一个切片(slice)表示一个数组内的连续分段,支持程序员指定底层存储的明确部分。构建一个切片 的语法与访问一个数组元素类似:

    /* Construct a slice on ary that starts at s and is len elements long */
    s1 := ary[s:len]

    /* Omit the length to create a slice to the end of ary */
    s2 := ary[s:]

    /* Slices behave just like arrays */
    s[0] == ary[s] //=> true

    // Changing the value in a slice changes it in the array
    ary[s] = 1
    s[0] = 42
    ary[s] == 42 //=> true

    该切片所引用的数组分段可以通过将新的切片赋值给同一变量来更改:

    /* Move the start of the slice forward by one, but do not move the end */
    s2 = s2[1:]

    /* Slices can only move forward */
    s2 = s2[-1:] // this is a compile error

    切片的长度可以更改,只要不超出切片的容量。切片s的容量是数组从s[0]到数组尾端的大小,并由内建的cap()函数返回。一个切片的长度永远不能超出它的容量。

    这里有一个展示长度和容量交互的例子:

    a := [...]int{1,2,3,4,5} // The ... means "whatever length the initializer has"
    len(a) //=> 5

    /* Slice from the middle */
    s := a[2:4] //=> [3 4]
    len(s), cap(s) //=> 2, 3

    /* Grow the slice */
    s = s[0:3] //=> [3 4 5]
    len(s), cap(s) //=> 3, 3

    /* Cannot grow it past its capacity */
    s = s[0:4] // this is a compile error

    通常,一个切片就是一个程序所需要的全部了,在这种情况下,程序员根本用不着一个数组,Go有两种方式直接创建切片而不用引用底层存储:

    /* literal */
    s1 := []int{1,2,3,4,5}

    /* empty (all zero values) */
    s2 := make([]int, 10) // cap(s2) == len(s2) == 10

    Map类型

    几乎每个现在流行的动态语言都有的数据类型,但在C中不具备的,就是dictionary。Go提供了一个基本的dictionary类型叫做map。下 面的例子展示了如何创建和使用Go map:

    m := make(map[string] int) // A mapping of strings to ints

    /* Store some values */
    m["foo"] = 42
    m["bar"] = 30

    /* Read, and exit program with a runtime error if key is not present. */
    x := m["foo"]

    /* Read, with comma-ok check; ok will be false if key was not present. */
    x, ok := m["bar"]

    /* Check for presence of key, _ means "I don't care about this value." */
    _, ok := m["baz"] // ok == false

    /* Assign zero as a valid value */
    m["foo"] = 0;
    _, ok := m["foo"] // ok == true

    /* Delete a key */
    m["bar"] = 0, false
    _, ok := m["bar"] // ok == false

    面向对象

    Go语言支持类似于C语言中使用的面向对象风格。数据被组织成structs,然后定义操作这些structs的函数。类似于Python,Go语言提供 了定义函数并调用它们的方式,因此语法并不会笨拙。

    Struct类型

    定义一个新的struct类型很简单:

    type Point struct {
    x, y float64
    }

    现在这一类型的值可以通过内建的函数new来分配,这将返回一个指针,指向一块内存单元,其所占内存槽初始化为零。

    var p *Point = new(Point)
    p.x = 3
    p.y = 4

    这显得很冗长,而Go语言的一个目标是尽可能的简明扼要。所以提供了一个同时分配和初始化struct的语法:

    var p1 Point = Point{3,4}  // Value
    var p2 *Point = &Point{3,4} // Pointer

    方法

    一旦声明了类型,就可以将该类型显式的作为第一个参数来声明函数:

    func (self Point) Length() float {
    return math.Sqrt(self.x*self.x + self.y*self.y);
    }

    这些函数之后可作为struct的方法而被调用:

    p := Point{3,4}
    d := p.Length() //=> 5

    方法实际上既可以声明为值也可以声明为指针类型。Go将会适当的处理引用或解引用对象,所以既可以对类型T,也可以对类型*T声明方式,并合理地使用它们。

    让我们为Point扩展一个变换器:

    /* Note the receiver is *Point */
    func (self *Point) Scale(factor float64) {
    self.x = self.x * factor
    self.y = self.y * factor
    }

    然后我们可以像这样调用:

    p.Scale(2);
    d = p.Length() //=> 10

    很重要的一点是理解传递给MoveToXY的self和其它的参数一样,并且是传递,而不是引用传递。如果它被声明为Point,那么在方法内修改的struct就不再跟调用方的一样&mdash;&mdash;值在它们传递给方法的时候被 拷贝,并在调用结束后被丢弃。

    接口

    像Ruby这样的动态语言所强调面向对象编程的风格认为对象的行为比哪种对象是动态类型(duck typing)更为重要。Go所 带来的一个最强大的特性之一就是提供了可以在编程时运用动态类型的思想而把行为定义的合法性检查的工作推到编译时。这一行为的名字被称作接口

    定义一个接口很简单:

    type Writer interface {
    Write(p []byte) (n int, err os.Error)
    }

    这里定义了一个接口和一个写字节缓冲的方法。任何实现了这一方法的对象也实现了这一接口。不需要像Java一样进行声明,编译器能推断出来。这既给予了动态类型的表达能力又保留了静态类型检查的安全。

    Go当中接口的运作方式支持开发者在编写程序的时候发现程序的类型。如果几个对象间存在公共行为,而开发者想要抽象这种行为,那么它就可以创建一个接口并使用它。

    考虑如下的代码:

    // Somewhere in some code:
    type Widget struct {}
    func (Widget) Frob() { /* do something */ }

    // Somewhere else in the code:
    type Sprocket struct {}
    func (Sprocket) Frob() { /* do something else */ }

    /* New code, and we want to take both Widgets and Sprockets and Frob them */
    type Frobber interface {
    Frob()
    }

    func frobtastic(f Frobber) { f.Frob() }

    需要特别指出的很重要的一点就是所有的对象都实现了这个空接口:

    interface {}

    继承

    Go语言不支持继承,至少与大多数语言的继承不一样。并不存在类型的层次结构。相较于继承,Go鼓励使用组合和委派,并为此提供了相应的语法甜点使其更容易接受。

    有了这样的定义:

    type Engine interface {
    Start()
    Stop()
    }

    type Car struct {
    Engine
    }

    于是我可以像下面这样编写:

    func GoToWorkIn(c Car) {
    /* get in car */

    c.Start();

    /* drive to work */

    c.Stop();

    /* get out of car */
    }

    当我声明Car这个struct的时候,我定义了一个匿名成员。这是一 个只能被其类型识别的成员。匿名成员与其它的成员一样,并有着和类型一样的名字。因此我还可以写成c.Engine.Start()。 如果Car并没有其自身方法可以满足调用的话,编译器自动的会将在Car上的调用委派给它的Engine上面的方法。

    由匿名成员提供的分离方法的规则是保守的。如果为一个类型定义了一个方法,就使用它。如果不是,就使用为匿名成员定义的方法。如果有两个匿名成员都提供一 个方法,编译器将会报错,但只在该方法被调用的情况下。

    这种组合是通过委派来实现的,而不是继承。一旦匿名成员的方法被调用,控制流整个都被委派给了该方法。所以你无法做到和下面的例子一样来模拟类型层次:

    type Base struct {}
    func (Base) Magic() { fmt.Print("base magic") }
    func (self Base) MoreMagic() {
    self.Magic()
    self.Magic()
    }

    type Foo struct {
    Base
    }
    func (Foo) Magic() { fmt.Print("foo magic") }

    当你创建一个Foo对象时,它将会影响Base的两个方法。然而,当你调用MoreMagic时, 你将得不到期望的结果:

    f := new(Foo)
    f.Magic() //=> foo magic
    f.MoreMagic() //=> base magic base magic

    并发

    Go的作者选择了消息传递模型来作为推荐的并发编程方法。该语言同样支持共享内存,然后作者自有道理:

    不要通过共享内存来通信,相反,通过通信来共享内存。

    该语言提供了两个基本的构件来支持这一范型:goroutineschannels

    Go例程

    Goroutine是轻量级的并行程序执行路径,与线程,coroutine或者进程类似。然而,它们彼此相当不同,因此Go作者决定给它一个新的名字并 放弃其它术语可能隐含的意义。

    创建一个goroutine来运行名为DoThis的函数十分简单:

    go DoThis() // but do not wait for it to complete

    匿名的函数可以这样使用:

    go func() {
    for { /* do something forever */ }
    }() // Note that the function must be invoked

    这些goroutine将会通过Go运行时而映射到适当的操作系统原语(比如,POSIX线程)。

    通道类型

    有了goroutine,代码的并行执行就容易了。然而,它们之间仍然需要通讯机制。Channel提供一个FIFO通信队列刚好能达到这一目的。

    以下是使用channel的语法:

    /* Creating a channel uses make(), not new - it was also used for map creation */
    ch := make(chan int)

    /* Sending a value blocks until the value is read */
    ch <- 4

    /* Reading a value blocks until a value is available */
    i := <-ch

    举例来说,如果我们想要进行长时间运行的数值计算,我们可以这样做:

    ch := make(chan int)

    go func() {
    result := 0
    for i := 0; i < 100000000; i++ {
    result = result + i
    }
    ch <- result
    }()

    /* Do something for a while */

    sum := <-ch // This will block if the calculation is not done yet
    fmt.Println("The sum is:", sum)

    channel的阻塞行为并非永远是最佳的。该语言提供了两种对其进行定制的方式:

    1. 程序员可以指定缓冲大小&mdash;&mdash;想缓冲的channel发送消息不会阻塞,除非缓冲已满,同样从缓冲的channel读取也不会阻塞,除非缓冲是空的。
    2. 该语言同时还提供了不会被阻塞的发送和接收的能力,而操作成功是仍然要报告。
    /* Create a channel with buffer size 5 */
    ch := make(chan int, 5)

    /* Send without blocking, ok will be true if value was buffered */
    ok := ch <- 42

    /* Read without blocking, ok will be true if a value was read */
    val, ok := <-ch

    Go提供了一种简单的机制来组织代码:包。每个文件开头都会声明它属于哪一个包,每个文件也可以引入它所用到的包。任何首字母大写的名字是由包导出的,并可以被其它的包所使用。

    以下是一个完整的源文件:

    package geometry

    import "math"

    /* Point is capitalized, so it is visible outside the package. */

    type Point struct {

    /* the fields are not capitalized, so they are not visible
    outside of the package */

    x, y float64
    }

    /* These functions are visible outside of the package */

    func (self Point) Length() float64 {
    /* This uses a function in the math package */
    return math.Sqrt(self.x*self.x + self.y*self.y)
    }

    func (self *Point) Scale(factor float64) {
    self.setX(self.x * factor)
    self.setY(self.y * factor)
    }

    /* These functions are not visible outside of the package, but can be
    used inside the package */

    func (self *Point) setX(x float64) { self.x = x }
    func (self *Point) setY(y float64) { self.y = y }

    缺失

    Go语言的作者试图将代码的清晰明确作为设计该语言作出所有决定的指导思想。第二个目标是生产一个编译速度很快的语言。有了这两个标准作为方向,来 自其它语言的许多特性就不那么适合了。许多程序员会发现他们最爱的语言特性在Go当中不存在,确实,有很多人也许会觉得Go语言由于缺乏其它语言所共有的 一些特性,还不太可用。

    这当中两个缺失的特性就是异常和泛型,两者在其它语言当中都是非常有用的。而它们目前都不是Go的一分子。但因为该 语言仍处于试验阶段,它们有可能最终会加入到语言里。然而,如果将Go与其它语言作比较的话,我们应当记住Go是打算在系统编程层面作为C语言的替代。明 白这一点的话,那么缺失的这许多特性倒也不是很大的问题了。

    最后,因为这一语言才刚刚发布,因此它没有什么类库或工具可以用,也没有Go语 言的集成编程环境。Go语言标准库有些有用的代码,但这与更为成熟的语言比 起来仍还是很少的。

    查看英文原文Google Go: A Primer


    感谢马国耀对本文的审校。

    给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家加入到InfoQ中文站用户讨论组中与我们的编辑和其他读者朋友交流。

  • Next page