大家给我个参考,做什么小吃比较好比较小,大概1

头图加载中...
关于三亚游
看了很多攻略,我大概总结了一下,4月和11月是游玩最佳季节,因为我临时决定去的,定的5月,这绝对不是一个好的时间。如果是有计划的旅游。建议4月和11月。
春节期间,旅游是旺季,价格要翻倍。有钱任性的就忽视我后面的心得。
4月是价格已经降下来,11月是价格还没涨上去。并且这2个月份天气温度都适宜。5月就很晒了,正夏天就更不谈了,9,10月台风季机票酒店都提前订好,碰上台风你就悲剧了。太晒真的很影响游玩。热都能忍,玩玩水吹吹海风真不会觉得难受,但是晒,真的很晒,海边10点就开始晒了,又没什么建筑物、树遮阴,你说怎么能愉快的玩耍?怎么愉快的自拍?眼睛都睁不开好吗!至少我在上的白天,基本就没出去晃,很浪费时光,都是花钱,去一趟不容易,不要因为烈日让旅程打折!
Day&1&&&&&5.&9日&晚上10点到机场,住大微蓝酒店
Day&2&&&&&5.10日&中午第一海鲜市场,饭后→森林公园鸟巢酒店,住鸟巢
Day&3&&&&&5.11日上午游森林公园,中午1:00,→,住
Day&4&&&&&5.12日下午3:30,前往湾,→椰梦长廊,住
Day&5&&&&&5.13日&休息一天(ps:原因后面说)晚上飞机回
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&关于机票&&&&
&5.9日周六&&&16:40虹桥起飞。其实这个时间太晚了,不好。第一天等于浪费了,但是虹桥出发的航班太少了,去浦东机场太远了,虹桥只有早上6点多,还有半夜的,然后还有下午3点出发,6点到的,其实也还行,悲剧的是显示只有1张,但是我们2人出发,当时觉得订好去程机票才能定酒店,惦记太烦就直接定了16:40的,其实隔天再刷新,15:00出发票额很多,而且还更便宜。郁闷。经验之谈,并不是越早定越便宜的,而且大家可以多刷刷不同的订票网站,我当时搜了去哪儿和淘宝去啊,当时显示下午3点的没有票,定完以后,突然想起来去搜搜携程,就有下午3点出发的了
另外,飞机晚点几率基本90%以上,走之前还和人吹牛说自己坐飞机基本没有遇过晚点的(其实是坐的太少,且近2年没有飞过,近两年飞机晚点才是正常)。再加上飞机晚点,本来预计19:45到的,最后9点多才到。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&关于酒店&
酒店换的太频繁。这点不好!不过还好不算太累。当时这样想的,定行程的时候就定了,森林公园和要去一下。那么就先定了这2个酒店,本来只准备住3晚,住完第四天就走,去程机票和3晚酒店都订好以后,看到各种攻略都推荐一定要去椰梦长廊看一场荡气回肠的日落,于是又临时加了一天行程,所以最后又赶到和第一天酒店很接近的,离机场不算太远的椰梦长廊附近住了一晚,其实如果计划好一点的话,机票定早一点飞的,下午3点多飞机到(别说我没提醒:预留1个半小时飞机晚点时间),定个椰梦长廊附近的酒店,从机场打车也就十几公里,放个行李休整一下,6点左右到椰梦长廊,确实美,值得一看(我那天云层厚,没看到),然后看完直接去吃顿海鲜,晚上早点休息,第二天早点出发去亚龙湾那边就棒棒哒了。
转回说到我定的酒店。第一晚定的是大的微蓝,网上推的比较火吧,不的。不算繁华市区,但是算城区吧。因为当天飞机会到的很晚,觉得定个海景酒店没必要,很浪费。例如后面定的鸟巢酒店,如果安排第一天,大晚上住过去,总觉得大材小用了。如果你票子多,全程都走星级的,就不用考虑我这么多了。我们休闲游,也是要把钱花在刀刃上,要花出价值来滴。&
&&&&&&&第二晚森林公园鸟巢酒店,因非诚勿扰而出名,因为森林公园大家都说要去,我是一个不喜欢早起风风火火赶行程的人,所以直接住景点是不二选择,森林公园山上就这一家酒店。没其他选择。不过森林公园山脚下马路对面有其他的酒店,应该便宜些,游森林也方便,到了门口需要坐景区巴士上山。酒店住客有专门的小缆车接送。另外酒店住客1个房间还含森林公园2张门票,一张也要130+,走索道20元。这么算下来一个房间也就600元,其实算下来和住山脚下差价不是很大了。
&&&&&&第三晚(一定要住一晚)不然白来了。白天人非常多,最晚的船是5点半(好像),所以基本5点就没啥人了,天又还挺亮,这才能让你好好感受的海边!上有2个酒店,都属于同一家,一个是珊瑚酒店。还有一个是木屋,木屋便宜200多吧,不过因为鸟巢已经体验过木屋了,所以岛上还是住的珊瑚酒店。定的珊瑚房标间1200元/晚,含双人船票和双早,船票168元/人,减去2人船票,早餐,也就800元吧,码头vip不用排队直接上船,比你住其他地方贵多少?想想来是干嘛的,早上8点的船过来,几点就要起床出发,然后码头大家都赶早来排队等,到了岛上已经很多人了,5点多就要返程,反正我是觉得有些钱可以省,有些钱应该花。如果还去,我会直接住2晚~
&&&&&第四晚&&。本来计划是下午离开直接乘酒店的免费送机大巴去机场的,还能省个车费,这也是我为什么把珊瑚酒店安排在第三晚,不过临时起意要去椰梦长廊,所以定了这家半夏,也是网上推荐很火的。(不推荐,后面详说)
另外,定在周六出发,因为周五去,周一回的机票要贵一点,在尽量时间上不太影响工作,又能花费少一点,周六去,周二回最好。还有一个原因,的星级酒店,周五和周六需要加100-200元,周日按平时价。所以我错时订房,周六住主题旅馆,是不分平时和周末价的。周日,周一住景区酒店。
为什么一定要住景区酒店?大概每个人对旅游的定义不同。旅游于我,是放松。早上6,7点起,然后拖着行李赶着人潮去景点,跟着人群走一圈,下午晚上再赶回去,累不说,美好的时间都花在了路上。当然我也并没有最好的利用到景区酒店的便利,只能说让我在最舒适的状态看看不一样的风景吧。另外每个旅游城市的目的不同,是一个感受风光的地方,本身酒店就是一个旅程,即使哪里都不去,就呆在星级酒店自带的范围,也能感受到愉悦。所以玩,就是玩酒店。如果你是游,那么就不一样了,是看的大都市,去的都是具体的一个个地点,并且交通都是很便利的,这时候定什么酒店真的无所谓,因为酒店没啥好逛的。靠不靠近你每天要去的点也不是太重要,只要你别住偏远郊区,地铁都很方便的。
游玩的地方,例如亚龙湾,森林公园,,真的没有便宜的小吃店。只能吃酒店的。不便宜。我没怎么在酒店吃,再预算有限的前提下,我愿意花多一点钱,住好风景的酒店,这个时候吃可以尽量省,只要吃饱不饿,吃的好不好真的不再考虑范围。因为吃的这些钱,你回去想吃多好的都可以,举例一天预算1000元,我会一天花960元定个海景酒店,10元吃一碗泡面,一点零食。再换1天在非景区,价格实惠的海鲜市场吃800元海鲜,住200元普通非景观酒店。
还有一些知名景点我没去,例如天涯海角,鹿回头公园等,这些都是人,好吧,我觉得我有人群恐惧症,再美好的风光,哪哪都是人,都觉得一点都不美了。另外天涯海角也就是海边多2个大石头,鹿回头公园这种,白天没啥好看,晚上我太累也不想跑了,反正就是不希望玩的太累,所以一些有的没的的地方,看完不会感概的地方,直接都pass了。
这次到全称交通是非常满意的。在去啊下单,然后新客户送2张50元接机送机一号专车抵用券,无比机智的用了2个账号2个手机号(一定要2个手机号)下单,一共送了4张50元券,订好机票就下单接机送机。一号专车司机可以看到你的航班,即使航班延误,也会等你航班到。一下机马上电话打来,在你步行最近的地方接你。
9号(一行4人)&机场→微蓝酒店:1号专车费用91-50优惠券=41元,19公里37分钟。
大家看下机场大巴对比我的专车接机,我是多么的机智!
10日&&微蓝酒店&&——&&&,往返都是打车,&&十几块钱,比较好打车,可能是因为淡季吧,而且是城区,不像其他攻略说的很难打车。
&&&&&&&&&微蓝酒店&——&森林公园鸟巢酒店&&&&酒店旁边坐交车25路,到亚龙湾的就上,基本沿线大酒店都能到。(一般星级酒店都会有接送大巴,鸟巢没有)
11日&&&森林公园鸟巢酒店&&→&码头&&&&提前一天预约珊瑚酒店接车,&基本亚龙湾各大酒店都会接到。只能预约早上9点和中午1点&2个时间。从鸟巢游客中心提前5分钟下去就可以了。到了珊瑚酒店大堂办好入住就可以预约第二天送车班车。
12日&&&因为定的是住宿在湾,所以选的是送到大广场,离湾最近了。打车也挺方便,到定的酒店15元左右。
13日&&&提前订好一号专车送机,半夏别馆到机场71-50抵用券=21元。15公里历时23分钟。
(ps:机场很小,从领登机牌到安检坐下候机,半个小时绰绰有余,提前40分钟到机场完全很充裕,不用太早)
飞机继续晚点,半夜12点才到虹桥,下机订好的一号专车接机车已等待。直接上车送回家。108元-50抵用券=58元,21公里26分钟。
整个旅程没有在交通上辛苦过。基本都是出门车都等好,重点是也没有多花钱呀。这点是我非常满意的。
--------------------------------------------------------
机场也有大巴,给大家参考一下&
&(机场国内候机楼到达大厅1号门)乘坐机场巴士&&
&1线&&&机场&←→&大
起讫时间:&09:00-24:00,第一位客人登车后15分钟内发车,客满随时发车;每日24:00后发车频率为1小时/班,每天首航、末航均有班车机动保障。全程用时约50分钟。&
收费标准:15元/人
去程路线:&机场&-&海虹路&-&国光豪生酒店&-&湾度假村&-&四二五医院&-&海月广场&-&外贸路口&-&中铁子悦薹&-&山水国际&-&鹿回头广场&-&大广场&-&各酒店。
3线&&机场&←→&亚龙湾
起讫时间:&09:30-24:00,第一位客人登车后30分钟内发车,客满随时发车;每日24:00后发车频率为1小时/班,每天首航、末航均有班车机动保障。全程约60分钟。&
收费标准:25元/人
去程路线:&镇&-&新一中&-&丹州小区&-&迎宾路&-&&-&同心家园&-&吉阳镇&-&安游路口&-&亚龙湾万豪酒店&-&亚龙湾中心广场&-&海底世界&-&仙人掌酒店&-&亚泰商业中心&-&各酒店。&
&&8&路&机场&——&市场&&&(机场一楼到达厅C门正对面乘坐)
首末班车时间:6:00&-&23:00
票价:5元/人
途径:机场&-&湾&-&路口&-&国光花园&-&湾度假村&-&景丽莱度假酒店&-&美丽新海岸小区&-&龙鲜酒楼&-&绿海田园小区&-&碧海篮天小区&-&425医院&-&海月广场&-&吉祥街口&-&团结街口&-&新风街口&-&水利大厦&-&汽车总站(旺豪超市)&-&市二中&-&一方百货&-&一市场路口&-&市委&-&鹿回头广场&
5.9日行程第一天
第一晚:下机直接上1号专车去预定的酒店。(订好机票后就提前预约好的1号专车接机。这点后面会详细说。强烈推荐)。微蓝酒店怎么说呢,主题酒店风格,还不错。算有特色的。大门招牌很小,几乎没看到。当时看了下地图,微蓝离不远(打车十几块钱吧),考虑到第二天中午要去吃海鲜方便,然后微蓝路口拐个弯,就有去亚龙湾的巴士,走路3-5分钟(上车还有座位),挺方便,装修比较有特色,第一晚就定了这家。
ps:晚上到的朋友,肚子饿的朋友,可以出微蓝酒店右手边一直走,绕一个半圆,有夜市海鲜,烧烤,炒菜。走路可达,价格也不贵,可以先询价。之前很怕遇到网上看的,手点了一下就得买,一顿上万的海鲜,心理很忐忑啊。这次我去感觉还好。旁边有个特产超市,价格也还好,不会觉得贵,买买水,小零食没有压力。
另外房间有一面是临马路,所以预定前最好打电话问清楚哪几间不靠马路的,定完再打电话确认一下房型。因为我就只打了一遍电话问安静的房型,没有再第二遍确认,有一间就临马路,好在是6楼,还多了1个小阳台,双层玻璃门,比较安静。下面有些房间没有阳台,就少了一层玻璃门,临马路睡眠不好的人就休息不好了。
去哪儿网预订的。共两间,一间特价227,一间292(然后入住当天手机订单签个到,账户再返44元),记得一定要签到,因为我看很多人评论忘了签到就没有返利)
ps:这种主题酒店都只有大床房。&&微蓝房间没有沐浴露,洗发水,牙刷,牙膏,毛巾。需要自带。如果没带牙刷牙膏,可以楼下前台免费取。我出门都是自带的,所以对我没影响。
晚上10点左右到的酒店,放了东西就出门逛逛了。然后绕到我上面提到的酒店旁边的大排档简单吃了点,因为飞机上吃的比较饱……第二天还要去一市场海吃,所以随便点了一点海鲜,大概180左右。
5.10日行程第二天,第一市场,森林公园鸟巢
睡到9点半起床。。。。,所以我这真的是休闲游啊,打扮下10点多退房,行李寄存再酒店,出门打个车直接去,15元不到吧(好像),就是个大型菜市场!路过市场门口接着走,马路两边很多海鲜加工店,都是先在海鲜市场像买菜一样买好海鲜,然后再找加工店加工的。你可以自己去买海鲜,也可以先找加工店,然后让加工店小妹带你买海鲜。我是去的网上热推的小胡子加工店,让小妹带我去挑的。我觉得味道一般啊,没觉得特别好吃。也就随便吃吃啊。芒果汁也好一般啊,还没有我在小眼镜喝的芒果汁好喝。现在还念念不忘。难道是我口味太挑?海鲜花了6,7佰,加工费300多。一顿1000块,觉得小贵啊。不过有个大龙虾180,6个螃蟹120,还有个鱼60,如果想实惠的话,就买濑尿虾啊,贝类海鲜,便宜,十几二十块一斤,还有一个本地的有点像蛤蜊,这个最便宜,但是最好吃。另外门口路过什么抱罗粉啊,清补凉啊,各买一碗尝过了,也觉得不好吃啊!!!那个抱罗粉,还没螺蛳粉好吃,大家都有那个臭臭的笋。
ps:还有个搞笑的,想问问几点关门哈,加工店服务员说xi点。“啊,7点?”&&“xi点”&&“11点?”&&&“xi点呀”&&&“7点?”&&&“xi点!!!”&&&“……啊……”&&&“8,9,xi的xi呀”&&&“哦,10点啊…………”&&&
吃饱喝足以后,海鲜还剩好多,犹豫了下,想着1000块,必须打包啊!!!再去市场里买了2个大芒果。回酒店拿行李大概1点多了,出门向车站方向走,就看到公交车已经停在站台了,好像是25路吧,反正写着亚龙湾,果断派一个人跑去拦车啊,司机就悠悠说,别跑了,我在这……上车都有座位,8元一人。这里提醒大家,上车先和售票员说你要去哪里,让她到了提醒你一下,我们到森林公园,就坐过站了,过了好几站不说,景区真的就是景区,别想着打车,根本看不到出。又坐回头公交,下车要往前走好远,太阳晒死了啊。本来如果不是坐过站正常方向下车过马路上个小坡十几米就到了啊。
下了公交就给鸟巢酒店客服打电话,然后上个坡到鸟巢游客接待中心,酒店的接待缆车就到了,直接接到酒店办理入住。效率比高多了!定的是集结地帐篷,930带卫浴,木有门哦!1300的集结地别墅,好像算一室一厅吧,多个门,想想贵400块,还是算了。酒店既然这么设计了,也开这么久,我想安全还是有保障的。反正我睡觉是门帘敞开的。最便宜的是麻雀房,公共卫浴,700多吧,这个就不考虑了。接下来重点来了,集结地帐篷旁一共只有5间,一定一定要预定11号房!一定要预定11号房!一定要预定11号房!重要的事要说3遍。我定了2间,非常幸运的有一间是11号,感觉非常棒,海景房,视野非常开阔,晚上坐在小露台吹着风,哪也不去都心情很好。另外一间就是树林里,如果是住11号房,我对鸟巢打100分,其他房就60分可住可不住。
本来留着一张房间分布图,可以看出其他房型哪些属于海景房,同样房型,景观不同也都是一样价格哦,那个册子丢了,大家可以网上搜搜有没有其他旅客上传过。
&&&&&&3点后入住的,如果到的早的话,可以先寄存行李,到时服务员会把行李提到房间,大家自己直接去逛了。
&&&&&&建议大家放下行李,带好泳衣,直接去峭壁泳池(有换衣间),游泳的感觉很棒。也可以直接穿着泳衣搭着罩衫。真的到了这些地方,这些都是自然而然的,穿着泳衣酒店走,真的就是自然而然的事。如果步行的话,可以穿过非诚勿扰舒淇走的索桥。看着没感觉,走上去有点脚软啊。住店旅客免费走。不想走路就早点打客房电话叫旅宾车门口接,直接送到峭壁泳池。
峭壁泳池,只有住店旅客才能进入哦
拍了上面那张照片,我就回房间拿泳衣了,再来,就没人了……整个泳池自己玩!
我的11号房。视野超级好。对了,集结地帐篷房没有空调的。只有1个电扇。我是5月10日入住,天气其实很热了。但是鸟巢根本不需要空调,房间非常凉快,特别是吹了自然风,我连电扇都没开,还盖了个浴巾。被子稍微有点厚了....
PS:浴室顶部有壁虎。看了很多评论,壁虎是必备的!
我之前说过中午打包的海鲜吧。晚上吹着风,在这个小露台吃着海鲜,啃着大芒果。真的太愉悦了。还有,海鲜没坏。中午吃觉得一般,此刻大家吃,一致觉得太美味了!担心芒果怎么切的,我不知道酒店有没有提供水果刀,应该没有,因为客房走到这里,还是要走一段路的,对面小店就有卖水果刀的,几块钱。买完芒果就买把刀好了。过了这几天丢掉也不心疼。
没有海景的其他集结地帐篷房。这个视野,瞬间弱了。一样的房型,一样的价格。不一样的体验。
那个著名的非诚勿扰索桥。红绸子哪去了!!!
走这个索桥,我个人建议,索桥好像是5点关,要么就是快关最后几分钟去,要么就一大早起床先走索桥,然后到了峭壁泳池那边再坐酒店接送车去餐厅。因为这时候没游客啊。
晚餐就是自带的吃食。看了攻略,鸟巢的泰餐味道还可以,人均1百多吧,当时想着饿了就去吃,结果自己带的吃完,也没饿,就没去吃。除了酒店的泰餐,还可以去百花谷吃。就是个商业街,全是吃饭的吧。类似必胜客或者炒菜类的。不是很远,但是不好坐车啊,走路有点远,打车就不好打。还听其他住客说,森林公园周围有个海鲜自助99元吃到饱的,具体是哪里,怎么去,大家自己去找找攻略。一开始的观念就是,到了这里好好玩,所以我不准备花太多时间在吃上面喽。就没太去搜攻略
5.11日第三天
森林公园,蜈支洲岛
11号房阳光是可以直射的,所以知了觉醒了。早上5,6点整片整片的知了让你感觉森林在尖叫!清晨那种凉凉的,真的很舒服,然后去吃早餐。这是一顿吃饱管3顿的模式!!!鸟巢酒店的早餐是可以好好享受的。
走之前,行李收拾好,放在房间,就可以出去了。不用回来退房。玩完打个电话或者直接去前台退房让服务员把行李送到游客中心就可以了,鸟巢的房间和游客中心各个地方都隔得比较远,没有必要来来回回浪费时间。
话说早上走的时候,晒在露台的衣服都没干,旁边放个袋子,也可以叫服务员中午退房时一起帮你收了装好带下来哦。
早餐。&&背后山中间,看到别墅了啊。估计是要上万的价格了
本篇游记共含11891个文字,59张图片。帮助了名游客。
京公网安备号
新出网证(京)字242号 全国统一客服电话:五步让你成为GO 语言高手
投稿:hebedich
字体:[ ] 类型:转载 时间:
本文给大家介绍的这里是GO程序员的五个进化阶段,从最开始的菜逼到最终的布道者,附上各种示例,一步步走向大神之路,推荐给小伙伴们,有需要的朋友可以参考下
Francesc () 是 Go 核心团队的一员, 是提倡 Google Cloud 平台的开发者. 他是一个编程语言的爱好者, Google的技术指导大师, Go tour的创造者之一. 这个讨论的灵感来自于另一个
在 JSConf. Slides 的讨论,这个讨论已经发到了.
是下一代编程协作工具, 用于搜索, 探索, 和审查代码. 我们参加GopherCon India 来分享我们是怎样使用 Go 并学习别人是怎样使用它的, 对配合liveblog的这次讨论我们深感荣幸.
作为Go团队的开发者之一,Francesc可能比世界上其他人接触到的Go语言程序员都要多。正因为有了这样的有利条件,他把Go语言的学习过程划分为5个阶段。
这些阶段对于其他语言的学习也是成立的。理解自己处于哪个阶段,可以帮助你找到提高自己的最有效的方法,也可以避免每个阶段学习过程中的常见陷阱。
编者按:这篇文章对于每一个学习阶段都给出了交互式的代码片段。点击函数名你就可以跳到具体的函数定义,方便进行深入的研究。请看下文。
这里是GO程序员的五个进化阶段:
: 刚刚学习了这门语言。 已经通过一些教程或者培训班了解基本的语法,可以写短的代码片段。
: 可以写一个完整的程序,但不懂一些更高级的语言特征,比如“channels”。还没有使用GO写一个大项目。
: 你能熟练的使用Go, 能够用GO去解决,生产环境中一个具体和完整的问题。已经形成了一套自己的惯用法和常用代码库。在你的编码方案中Go是一个非常好用的工具。
: 绝逼清楚Go语言的设计选择和背后的动机。能理解的简洁和可组合性哲学。
: 积极地与他人分享关于Go语言知识和你对Go语言的理解。在各种合适的场所发出自己的声音, 参与邮件列表、建立QQ群、做专题报告。成为一个布道者不见得是一个完全独立的阶段,这个角色可以在上述的任何一个阶段中。
第一阶段: 菜逼
菜鸟在这个阶段使用Go去创建一些小项目或者玩具项目。他们应该会利用到, , , 和邮件列表().
func main() {&&& fmt.Println(stringutil.Reverse("!selpmaxe oG ,olleH"))}
这是Go语言写的简单例子,这个代码段来自代码库里面的 hello.go 。 点击就可以查看完整代码撸。
一项重要的技能,新人应该试着学习如何正确提问。很多新人在邮件列表里面这样说“嘿,这报错了”,这并没有提供足够的信息,让别人能理解并帮助他们解决问题。别人看到的是一个粘贴了几百行的代码的帖子,并没有花费精力来重点说明所遇到的问题。
所以, 应该尽量避免直接粘贴代码到论坛。而应该使用可以编辑并且可以在浏览器中直接运行的Go playground的“分享”按钮链接到代码片段。
Phase 2: the explorer
探索者已经可以使用Go写一些小的软件,但有时仍然会有些迷茫。他们可能不完全明白怎么使用Go的高级特性,比如通道。虽然他们还有很多东西要学习,但已掌握的足够做一些有用的事情了!他们开始对Go的潜能有感觉了,并对它们能使用Go创建的东西感到兴奋。
在探索阶段通常会经历两个步骤。第一,膨胀的预期达到顶点,你觉得可以用Go做所有的事情,但还并不能明白或领悟到Go的真谛。你大概会用所熟悉的语言的模式和惯用语来写Go代码,但对于什么是地道的Go,还没有比较强烈的感觉。你开始尝试着手干这样的事情--“迁移架构X,从Y语言到Go语言”。
到达预期膨胀的顶点之后,你会遇到理想幻灭的低谷。你开始想念语言Y的特性X,此时你还没有完全的掌握地道的Go。你还在用其他编程语言的风格来写Go语言的程序,你甚至开始觉得沮丧。你可能在大量使用reflect和unsafe这两个包,但这不是地道的Go。地道的Go不会使用那些魔法一样的东西。
这个探索阶段产生的项目的一个很好的例子就是。Martini是一个Go语言的早期Web框架,它从Ruby的Web框架当中吸收了很多思想(比如依赖注入)。最初,这个框架在社区中引起了强烈的反响,但是它逐渐在性能和可调试性上受到了一些批评。Martini框架的作者Jeremy Saenz积极响应这些来自Go社区的反馈,写了一个更加符合Go语言规范的库
func (m *Martini) RunOnAddr(addr string) {&&& // TODO: Should probably be implemented using a new instance of http.Server in place of&&& // calling http.ListenAndServer directly, so that it could be stored in the martini struct for later use.&&& // This would also allow to improve testing when a custom host and port are passed.&&&& logger := m.Injector.Get(reflect.TypeOf(m.logger)).Interface().(*log.Logger)&&& logger.Printf("listening on %s (%s)\n", addr, Env)&&& logger.Fatalln(http.ListenAndServe(addr, m))}
来自Martini框架的交互式代码片段,它是不地道的Go的例子。注意用反射包实现的依赖注入
func TestNegroniServeHTTP(t *testing.T) {&&& result := ""&&& response := httptest.NewRecorder()&&&& n := New()&&& n.Use(HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {&&&&&&& result += "foo"&&&&&&& next(rw, r)&&&&&&& result += "ban"&&& }))&&& n.Use(HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {&&&&&&& result += "bar"&&&&&&& next(rw, r)&&&&&&& result += "baz"&&& }))&&& n.Use(HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {&&&&&&& result += "bat"&&&&&&& rw.WriteHeader(http.StatusBadRequest)&&& }))&&&& n.ServeHTTP(response, (*http.Request)(nil))&&&& expect(t, result, "foobarbatbazban")&&& expect(t, response.Code, http.StatusBadRequest)}
来自Negroni库的交互式代码片段,它是地道的Go的例子
其他语言在提供一些核心功能,比如HTTP处理的时候,往往需要依赖第三方库。但是Go语言在这一点上很不同,它的标准库非常强大。如果你认为Go标准库没有强大到可以做你想做的事情,那么我说你错了。Go语言标准库难以置信的强大,值得你花时间阅读它的代码,学习它实现的模式。
func (srv *Server) ListenAndServe() error {&&& addr := srv.Addr&&& if addr == "" {&&&&&&& addr = ":http"&&& }&&& ln, err := net.Listen("tcp", addr)&&& if err != nil {&&&&&&& return err&&& }&&& return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})}
Go标准库中的ListenAndServe函数片段。如果你写过Go程序,你可能已经调用过这个函数很多次了,但是你曾经花时间看过它的实现么?去点击上面的代码片段吧。
幻灭的低谷中的幻灭感来自于这样的事实:你还在用其他语言的模式来想问题,而且你还没有完全探索过Go能提供给你什么。下面是一些好玩的事情,你可以做一下来打破困境,进一步探索这门语言中好玩的事。
go generate
现在来看看go generate。go generate是一个你可以用来自动自成Go代码的命令。你可以结合例如jsonenums(一个用于为枚举类型自动生成JSON编组样板代码的类库)这样的元编程来使用go generate快速自动实现重复乏味代码的编写。在Go标准类库里面已经有大量可以用于解析AST的接口,而AST使得编写元编程工具更简单,更容易。在会议上,有另外两次讨论(和)谈及到了这一点。
func main() {&&& flag.Parse()&&& if len(*typeNames) == 0 {&&&&&&& log.Fatalf("the flag -type must be set")&&& }&&& types := strings.Split(*typeNames, ",")&&&& // Only one directory at a time can be processed, and the default is ".".&&& dir := "."&&& if args := flag.Args(); len(args) == 1 {&&&&&&& dir = args[0]&&& } else if len(args) & 1 {&&&&&&& log.Fatalf("only one directory at a time")&&& }&&&& pkg, err := parser.ParsePackage(dir, *outputSuffix+".go")&&& if err != nil {&&&&&&& log.Fatalf("parsing package: %v", err)&&& }&&&& var analysis = struct {&&&&&&& Command&&&&&&& string&&&&&&& PackageName&&& string&&&&&&& TypesAndValues map[string][]string&&& }{&&&&&&& Command:&&&&&&& strings.Join(os.Args[1:], " "),&&&&&&& PackageName:&&& pkg.Name,&&&&&&& TypesAndValues: make(map[string][]string),&&& }&&&& // Run generate for each type.&&& for _, typeName := range types {&&&&&&& values, err := pkg.ValuesOfType(typeName)&&&&&&& if err != nil {&&&&&&&&&&& log.Fatalf("finding values for type %v: %v", typeName, err)&&&&&&& }&&&&&&& analysis.TypesAndValues[typeName] = values&&&&&&&& var buf bytes.Buffer&&&&&&& if err := generatedTmpl.Execute(&buf, analysis); err != nil {&&&&&&&&&&& log.Fatalf("generating code: %v", err)&&&&&&& }&&&&&&&& src, err := format.Source(buf.Bytes())&&&&&&& if err != nil {&&&&&&&&&&& // Should never happen, but can arise when developing this code.&&&&&&&&&&& // The user can compile the output to see the error.&&&&&&&&&&& log.Printf("warning: internal error: invalid Go generated: %s", err)&&&&&&&&&&& log.Printf("warning: compile the package to analyze the error")&&&&&&&&&&& src = buf.Bytes()&&&&&&& }&&&&&&&& output := strings.ToLower(typeName + *outputSuffix + ".go")&&&&&&& outputPath := filepath.Join(dir, output)&&&&&&& if err := ioutil.WriteFile(outputPath, src, 0644); err != nil {&&&&&&&&&&& log.Fatalf("writing output: %s", err)&&&&&&& }&&& }}
一段互动的片段演示了如何编写jsonenums命令。
许多人使用Go作web服务,但是你知道你也可以用Go写出很cool的图形应用吗?查看。
func main() {&&& glfw.SetErrorCallback(errorCallback)&&&& if !glfw.Init() {&&&&&&& panic("Can't init glfw!")&&& }&&& defer glfw.Terminate()&&&& window, err := glfw.CreateWindow(Width, Height, Title, nil, nil)&&& if err != nil {&&&&&&& panic(err)&&& }&&&& window.MakeContextCurrent()&&&& glfw.SwapInterval(1)&&&& gl.Init()&&&& if err := initScene(); err != nil {&&&&&&& fmt.Fprintf(os.Stderr, "init: %s\n", err)&&&&&&& return&&& }&&& defer destroyScene()&&&& for !window.ShouldClose() {&&&&&&& drawScene()&&&&&&& window.SwapBuffers()&&&&&&& glfw.PollEvents()&&& }}
交互式的片段正说明Go的OpenGL捆绑能制作Gopher cube。点击函数或方法名去探索。
黑客马拉松和挑战
你也可以观看挑战和黑客马拉松,类似和。在过去,来自世界各地的程序员一起挑战一些真实的酷项目,你可以从中获取灵感。
第三阶段: 老手
作为一个老手,这意味着你可以解决很多Go语言中你关心的问题。新的需要解决的问题会带来新的疑问,经过试错,你学会了在这门语言中什么是可以做的,什么是不能做的。此时,你已经对这门语言的习惯和模式有了一个坚实的理解。你可以非常高效地工作,写出可读,文档完善,可维护的代码。
成为老手的一个很好的方法就是在大项目上工作。如果你自己有一个项目的想法,开始动手去做吧(当然你要确定它并不是已经存在了)。大多数人也许并没有一个很大的项目的想法,所以他们可以对已经存在的项目做出贡献。Go语言已经有很多大型项目,而且它们正在被广泛使用,比如Docker, Kubernetes和Go本身。可以看看这个
func (cli *DockerCli) CmdRestart(args ...string) error {&&& cmd := cli.Subcmd("restart", "CONTAINER [CONTAINER...]", "Restart a running container", true)&&& nSeconds := cmd.Int([]string{"t", "-time"}, 10, "Seconds to wait for stop before killing the container.")&&& cmd.Require(flag.Min, 1)&&&& utils.ParseFlags(cmd, args, true)&&&& v := url.Values{}&&& v.Set("t", strconv.Itoa(*nSeconds))&&&& var encounteredError error&&& for _, name := range cmd.Args() {&&&&&&& _, _, err := readBody(cli.call("POST", "/containers/"+name+"/restart?"+v.Encode(), nil, false))&&&&&&& if err != nil {&&&&&&&&&&& fmt.Fprintf(cli.err, "%s\n", err)&&&&&&&&&&& encounteredError = fmt.Errorf("Error: failed to restart one or more containers")&&&&&&& } else {&&&&&&&&&&& fmt.Fprintf(cli.out, "%s\n", name)&&&&&&& }&&& }&&& return encounteredError}
Docker项目的交互式代码片段。点击函数名,开始探索之旅吧。
老手应该对Go生态系统的工具有一个很强的掌握,因为这些工具真的提高生产效率。你应该了解go generate,go vet,go test-race, 和gofmt/goimports/goreturns。你应该使用go fmt,因为它会自动把你的代码按照Go社区的风格标准来格式化。goimports可以做同样的事情,而且还会添加丢失的imports。goretures不光做了前面所说的事情,还可以在返回表达式添加丢失的错误,这是大家都讨厌的地方。
在老手阶段,你一定要开始做code review。code review的意义并不是要修改或者找到错误(那是测试人员做的事情)。code review可以帮助维持统一的编程风格,提高软件的总体质量,还可以在别人的反馈中提高你自己的编程技术。几乎所有的大型开源项目都对每一个提交做code review。
下面是一个从人类的反馈当中学习的例子:Google的Go团队以前都在main函数的外面声明命令行标记。在去年的GopherCon会议上,Francesc遇到了SoundCloud公司的Peter Bourgon(@peterbourgon)。Peter Bourgon说在SoundCloud,他们都在main函数内部声明标记,这样他们不会错误地在外部使用标记。Francesc现在认为这是最佳实践。
第四阶段:专家
作为一个专家,你很好地了解了语言的哲学思想。对于Go语言的特性,你知道何时应该使用,何时不应该使用。例如,Jeremy Saenz在中谈论到了何时不该使用接口。
func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call {&&& call := new(Call)&&& call.ServiceMethod = serviceMethod&&& call.Args = args&&& call.Reply = reply&&& if done == nil {&&&&&&& done = make(chan *Call, 10) // buffered.&&& } else {&&&&&&& // If caller passes done != nil, it must arrange that&&&&&&& // done has enough buffer for the number of simultaneous&&&&&&& // RPCs that will be using that channel.& If the channel&&&&&&& // is totally unbuffered, it's best not to run at all.&&&&&&& if cap(done) == 0 {&&&&&&&&&&& log.Panic("rpc: done channel is unbuffered")&&&&&&& }&&& }&&& call.Done = done&&& client.send(call)&&& return call}
来自标准类库的一小块交互代码片段使用了频道。理解标准类库里面的模式背后的决策原因是成为一个专家必经之路。
但是不要成为只局限于单一语言的专家。跟其他任何语言一样,Go仅仅只是一个工具。你还应该去探索其他语言,并且学习他们的模式和风格。Francesc从他使用Go的经验中找到了编写JavaScript的启发。他还喜欢重点关注于不可变性和致力于避免易变性的Haskell语言,并从中获得了如何编写Go代码的灵感。
作为一个布道者,你分享自己的知识,传授你学会的和你提出的最佳实践。你可以分享自己对Go喜欢或者不喜欢的地方。全世界各地都有Go会议,。
你可以在任何一个阶段成为布道者,不要等到你成为这个领域的专家的时候才发出自己的声音。在你学习Go的任何一个阶段,提出问题,结合你的经验给出反馈,不要羞于提出自己不喜欢的地方。你提出的反馈可以帮助社区改善做事情的方法,也可能改变你自己对编程的看法。
func main() {&&& httpAddr := flag.String("http", "127.0.0.1:3999", "HTTP service address (e.g., '127.0.0.1:3999')")&&& originHost := flag.String("orighost", "", "host component of web origin URL (e.g., 'localhost')")&&& flag.StringVar(&basePath, "base", "", "base path for slide template and static resources")&&& flag.BoolVar(&present.PlayEnabled, "play", true, "enable playground (permit execution of arbitrary user code)")&&& nativeClient := flag.Bool("nacl", false, "use Native Client environment playground (prevents non-Go code execution)")&&& flag.Parse()&&&& if basePath == "" {&&&&&&& p, err := build.Default.Import(basePkg, "", build.FindOnly)&&&&&&& if err != nil {&&&&&&&&&&& fmt.Fprintf(os.Stderr, "Couldn't find gopresent files: %v\n", err)&&&&&&&&&&& fmt.Fprintf(os.Stderr, basePathMessage, basePkg)&&&&&&&&&&& os.Exit(1)&&&&&&& }&&&&&&& basePath = p.Dir&&& }&&& err := initTemplates(basePath)&&& if err != nil {&&&&&&& log.Fatalf("Failed to parse templates: %v", err)&&& }&&&& ln, err := net.Listen("tcp", *httpAddr)&&& if err != nil {&&&&&&& log.Fatal(err)&&& }&&& defer ln.Close()&&&& _, port, err := net.SplitHostPort(ln.Addr().String())&&& if err != nil {&&&&&&& log.Fatal(err)&&& }&&& origin := &url.URL{Scheme: "http"}&&& if *originHost != "" {&&&&&&& origin.Host = net.JoinHostPort(*originHost, port)&&& } else if ln.Addr().(*net.TCPAddr).IP.IsUnspecified() {&&&&&&& name, _ := os.Hostname()&&&&&&& origin.Host = net.JoinHostPort(name, port)&&& } else {&&&&&&& reqHost, reqPort, err := net.SplitHostPort(*httpAddr)&&&&&&& if err != nil {&&&&&&&&&&& log.Fatal(err)&&&&&&& }&&&&&&& if reqPort == "0" {&&&&&&&&&&& origin.Host = net.JoinHostPort(reqHost, port)&&&&&&& } else {&&&&&&&&&&& origin.Host = *httpAddr&&&&&&& }&&& }&&&& if present.PlayEnabled {&&&&&&& if *nativeClient {&&&&&&&&&&& socket.RunScripts = false&&&&&&&&&&& socket.Environ = func() []string {&&&&&&&&&&&&&&& if runtime.GOARCH == "amd64" {&&&&&&&&&&&&&&&&&&& return environ("GOOS=nacl", "GOARCH=amd64p32")&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&& return environ("GOOS=nacl")&&&&&&&&&&& }&&&&&&& }&&&&&&& playScript(basePath, "SocketTransport")&&&&&&& http.Handle("/socket", socket.NewHandler(origin))&&& }&&& http.Handle("/static/", http.FileServer(http.Dir(basePath)))&&&& if !ln.Addr().(*net.TCPAddr).IP.IsLoopback() &&&&&&&&& present.PlayEnabled && !*nativeClient {&&&&&&& log.Print(localhostWarning)&&& }&&&& log.Printf("Open your web browser and visit %s", origin.String())&&& log.Fatal(http.Serve(ln, nil))
流行的present命令的main函数,很多Go的用户使用它来制作幻灯片。许多演讲者修改了这个模块来满足自己的需要。
问:在GO语言中,我所怀念的一项功能是一个好的调试器。
答:我们正在做了,不只是调试器,我们还会提供一个更好的总体监视工具可以让你在程序运行时更好地洞察程序在干什么(显示出所有正在运行的goroutine的状态)。在GO 1.5中探索它吧。
以上所述就是本文的全部内容了,希望大家能够喜欢。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具

我要回帖

更多关于 做什么小吃比较挣钱 的文章

 

随机推荐