我为什么喜欢Go语言123123
从2000年至今,也写了11年代码了,期间用过VB、Delphi、C#、C++、Ruby、Python,一直在寻找一门符合自己心意和理念的语言。我很在意写代码时的手感和执行的效率,所以在Go出现之前一直没有找到。在熟悉Go之后,我虽没有停下脚步,也去体验了D语言,但几乎立即就放弃了,它的设计还是太复杂。
就说说Go吧。它的好其实也就两个字——简洁!
看很多朋友的留言都觉得这些“少个括号、少个分号”之类的东西没什么意义,真的吗?问题是,既然可以没有,为什么非得有?既然能够少打一个字符,为什么多打了还挺开心?还觉得天经地义?这里简单一点,那里简单一点,总的来说是不是就简单了很多?这里的设计简洁一点,那里简洁一点,是否整体就是紧凑高效?
很多东西,要整体去体会,才能感觉到真正的强大。没有前面这些语法上的各种“看起来没什么用”的支持,怎么能做到后面提到的那些设计上的简洁?
我坚信,少就是多,简单就是强大,不能减一分的设计才是真正的好设计!
简洁的变量声明和赋值
拿最简单的声明变量和赋值来看,下面这一句完成了声明类型到赋值,最后还有那个常见的分号作为语句的结束。
var i int = 10;
这个一点都不简洁对吧?为什么非要有“var”?为什么不能自己推导变量类型?为什么结尾非要加上分号?这三个问题,我相信Go语言的设计者也问过,并且都针对性的给了改进。重新来过。
i := 10
怎么样?“:=”是声明并推导类型的语法糖,结尾的分号也省了,因为这里我换行了,编译器明白的。
还可以一次性声明并赋值多个变量。
i, j, k := 1, 2, 3
不同的类型也可以。
i, j, k := 1, 1.0, “hello”
如果要声明一堆变量,但暂时不赋值呢?可以这样。
var (
- i, j int
- s string
- u, v, s = 2.0, 3.0, "bar"
)
Go的设计者甚至觉得多打几个“var”都不应该!
简洁的if
有点意思了对吧?我学习一门新语言的时候,第一眼看变量类型和声明,第二眼就会去看逻辑控制的语法。现在来看看都有些什么?
if i > 10 {
println(“Greater then 10”)
}
稀松平常啊,难道一个简单的if还能更简单?恩,的确是的。首先if后面的条件判断没有人逼你再加上括号了,仅仅是少了两次按键嘛,还有呢?还有!下面这个应该是很常见的if使用场景。
result := SomeMethod()
if result > 0 {
}
很多时候result这个变量其实仅仅用于条件判断,完全可以在if之后就扔掉,所以Go有了这么个写法。
if result := SomeMethod(); result > 0 {
}
这个表达式太常用了,真是谁写谁知道,每次我写着一行都会心里一爽。来看看纠结一点的if段。
if a {
} else if b {
} else if c {
} else {
}
这种写法是可以的,但不是Go推荐的,理由是可以更简洁。比如强悍的switch。
强悍的switch
这是很大家熟知的switch用法,注意,没有break哦!Go里面case之间不会“下穿”。
- switch tag {
- default:
- s3()
- case 0, 1, 2, 3:
- s1()
- case 4, 5, 6, 7:
- s2()
- }
- 神奇一点的switch,嘿嘿,与if异曲同工之妙。
- switch x := f(); { // missing switch expression means "true"
- case x < 0: return -x
- default: return x
- }
还有这个,有了这个更加明确的写法,你真的还会if…else if…else if…else…吗?
- switch {
- case x < y: f1()
- case x < z: f2()
- case x == 4: f3()
- }
条件判断舒服了,循环呢?
孤单的for
其实我一直不太明白,为什么一门语言里面要提供多个循环语法呢?for、while、do…while…都是不可替代的?用哪一个呢?似乎都是看个人爱好吧?可能大家随便就可以举个例子出来证明这三个东西存在的必要和细微的差别,但对于我来说,做同一件事情如果有多种方法其实就是设计上的冗余,会对使用者造成或多或少的困扰。来看看Go的循环吧。
for i := 0; i < 10; i++ {
}
for a < b {
}
for {
}
看吧,一个for就搞定所有情况了。来看一个常用的遍历集合,一把来说会写成这样。
count := len(someArray)
for i := 0; i < count; i++ {
println(someArray[i])
}
简化这个,Go给出了一个关键字“range”,先看用法。
for i, value := range someArray {
// i 是整型,代表下标
// value就是数组内值的类型
}
range不单单可以用于数组,实际上它可以用于任何集合,比如map。
- m := map[string]int{"mon":0, "tue":1, "wed":2, "thu":3, "fri":4, "sat":5, "sun":6}
- for i, s := range a {
- // type of i is int
- // type of s is string
- }
这里只是提到了几点最基本的语法场景,Go里面还有很多!
函数可以返回多个值
其实能够在一行多重赋值的语言挺多的,但一个函数能返回多个值的就很少了,比如在C#里面如果要返回两个int,通常会这么干。
public class TwoInts
{
public int A;
public int B;
}
public class Foo
{
public TwoInts ReturnTwoInt();
}
然后就可以 TwoInts ti = foo.CalcTwoInt() 觉得悲催吗?也许你都麻木了对吗?很多语言都是这么设计的。函数只能返回一个值最大的问题是会导致出现很多没必要的数据结构。上面就体现了这个冗余,当然,你说可以用out关键字让函数返回,但这个语法用起来就不是那么安全了。而这个问题在Go里面解决起来太容易了,因为Go的函数可以返回多个值!
func returnTwoInt() (int, int) {
}
a, b := returnTwoInt()
我对Go的好感就是从这里萌芽的,这让我的库里面从此少了很多数据结构!这无形中就能降低设计的复杂度。
函数内部声明的对象指针可以安全的返回
func ReturnPointer() *Object1 {
obj := new Object1()
obj.A = “hello”
return obj
}
Go的垃圾回收器会处理好这种情况的,放心啦!
异常处理?defer是啥?能吃吗?
为什么异常处理那么复杂?多少人可以安全的实现下面这个逻辑?以下是伪代码。
File f = File.Read(“c:\\text.txt”)
f.Write(xxx)
f.Close()
我相信,有经验的码农们脑子里面瞬间出现了各种版本的try…catch…finally…,还有各种各样的书写规范,比如“catch”里面的逻辑不能在抛异常之类的东西。其实想想,我们的要求很简单,打开一个文件,然后保证它在最后被关闭。仅此而已,为什么做这么简单的一件事情非要那么复杂?看看人家Go是怎么做的!
func SaveSomething() {
if f, err := os.Open(“c:\\text.txt”); err == nil {
//各种读写
defer f.Close()
}
}
凡是加了defer的函数,都会在当前函数(这里就是SaveSomething)执行完毕之后执行。就算“//各种读写”时发生异常f.Close也会坚定的在SaveSomething退出时被执行。有了这个,释放点资源,关闭个把句柄这种小事再也无足挂齿!
接口再也不用“实现”了
从我接触OO思想一来,凡是有接口的语言,都以不同的方式要求类“实现”接口,这样的方式我一直都认为是天经地义的,直到我遇见了Go。
type Speaker interface {
Say()
}
上面定义了一个接口,只有一个方法,Say,不需要参数,也没有返回值。Go里面,任何拥有某个接口所定义所有方法的东西,都默认实现了该接口。这是一句拥有太多内涵的话,足矣对设计思路产生重大的影响。比如下面这个方法,它接受一个类型为Speaker的参数。
func SaySomething(s Speaker) {
s.Say()
}
那么所有拥有Say()方法的东西都可以往里扔。
在Go的世界里,所有的东西都默认实现了interface{}这个接口。有了这个概念,即使没有泛型也能有效的降低设计复杂度。
多线程还能更简单点吗?
要写多线程,你要懂Thread,懂各种锁,懂各种信号量。在各类系统里面,“异步”逻辑通常代表“困难”。这是Go最强劲的部分,你见过比下面这个还简单的异步代码吗(以下代码摘自Go的官方范例)?
func IsReady(what string, minutes int64) {
time.Sleep(minutes * 60*1e9);
fmt.Println(what, "is ready")
}
go IsReady("tea", 6);
go IsReady("coffee", 2);
fmt.Println("I'm waiting....");
执行的结果是,打印:
I'm waiting.... (right away)
coffee is ready (2 min later)
tea is ready (6 min later)
Go语言内置了“go”这个语法,任何go的方法,都将会被异步执行。那异步方法之前传递消息呢?用channel呗。意如其名,就是一个管道,一个往里写,另外一个等着读。
ch := make(chan int) //创建一个只能传递整型的管道
func pump(ch chan int) {
for i := 0; ; i++ { ch <- i } //往管道里写值
}
func suck(ch chan int) {
for { fmt.Println(<-ch) } //这里会等着直到有值从管道里面出来
}
go pump(ch) //异步执行pump
go suck(ch) //异步执行suck
嘿嘿,然后你就看到控制台上输出了一堆数字。
这次就写到这儿吧,对不住Go里面其他的好东西了,哥饿了,就不一一出场亮相了,抱歉抱歉!鞠躬!下台!
http://www.cnblogs.com/AllenDang/archive/2012/03/03/2378534.html
我为什么喜欢Go语言123123的更多相关文章
- 我为什么喜欢Go语言
从2000年至今,也写了11年代码了,期间用过VB.Delphi.C#.C++.Ruby.Python,一直在寻找一门符合自己心意和理念的 语言.我很在意写代码时的手感和执行的效率,所以在Go出现之前 ...
- 最近为毛喜欢上C/C++语言了
旁观者李四说:此人大笨也!我用鼠标随便拖几个控件, 就是一个xxx管理系统了,你用C语言怕是一年也写不出来吧! 好吧,我要承认,讲这话的都已经是mS的奴才了,别的我不了解, MFC本身就是一个封闭的架 ...
- 用Go语言做产品半年的一些感觉
用Go语言做产品刚好半年,有一些感觉跟大家说道说道. 在使用Go之前,我常常想象,无法使用先进的Debug工具会对工作进度造成多么巨大的影响.甚至在Visual Studio的娇惯下认为,不能调试基本 ...
- 【GoLang】转载:我为什么放弃Go语言,哈哈
我为什么放弃Go语言 作者:庄晓立(Liigo) 日期:2014年3月 原创链接:http://blog.csdn.NET/liigo/article/details/23699459 转载请注明出处 ...
- 2.NopCommerce中文语言包
由于NopCommerce是纯英语环境,给英语不好的管理人员带来诸多不便. NopCommerce支持多语言环境,所以我们只要安装中文语言包,让NopCommerce支持后台中文操作环境. 首先先下载 ...
- R语言的前世今生(转)
最近因病休养在家,另外也算是正式的离开Snack Studio.终于有了大把可以自由支配的时间.可以自主的安排.最近闲暇的时间总算是恶补了不少前段时间行业没有时间关注的新事物.看着行业里引领潮流的东西 ...
- C 语言 .h文件的作用
C语言头文件的作用 最近在工作当中遇到了一点小问题,关于C语言头文件的应用问题,主要还是关于全局变量的定义和声明问题.学习C语言已经有好几年了,工作使用也近半年了,但是对于这部分的东西的确还没有深入的 ...
- Lambda表达式(C语言-gcc编译器)
前言 先来啰嗦几句,身边的朋友,同事都喜欢在博客上记录自己在学习计算机编程技术路程上的一些问题和心得.就我个人而言,这是个好习惯,特别是在计算机编程领域,技术方向种类繁多,永无止境.所以,我也开始我人 ...
- Perl,Python,Ruby,Javascript 四种脚本语言比较
Perl 为了选择一个合适的脚本语言学习,今天查了不少有关Perl,Python,Ruby,Javascript的东西,可是发现各大阵营的人都在吹捧自己喜欢的语言,不过最没有争议的应该是Javascr ...
随机推荐
- UNIX网络编程读书笔记:地址操纵函数
地址格式转换函数:它们在ASCII字符串(人们比较喜欢用的格式)与网络字节序的二进制值(此值存于套接口地址结构中)间转换地址. 1.inet_aton.inet_addr.inet_ntoa inet ...
- TP模板中如何使用函数
TP模板中如何使用函数 TP中如何将时间戳转换为时间显示 我们往往需要对模板输出变量使用函数,可以使用: {$data.name|md5} 编译后的结果是: <?php echo (md5($d ...
- webpack 编译less/scss文件
1.安装插件 处理less: npm install less-loader --save-dev 处理sass: npm install sass-loader --save-dev 2.项目目录: ...
- Learning English From Android Source Code:1
英语在软件行业的重要作用不言自明,尤其是做国际项目和写国际软件,好的英语表达是项目顺利进行的必要条件.纵观眼下的IT行业.可以流利的与国外客户英文口语交流的程序猿占比并非非常高.要想去国际接轨,语言这 ...
- putty(winscp)无法连接到linux(ubuntu)
为了能在自己笔记本电脑上兼容公司的用64位系统编译出来的MapReduce程序,我把自己原来32位的ubuntu虚拟机删除后,安装了目前最新的ubuntu-14.04.2-desktop-amd64. ...
- JavaScript 参考教程
JavaScript 是使用“对象化编程”的,或者叫“面向对象编程”的.所谓“对象化编程”,意思是把 JavaScript 能涉及的范围划分成大大小小的对象,对象下面还继续划分对象直至非常详细为止,所 ...
- ubuntu sudo 和su的区别
ubuntu用户管理 sudo意思就是super-user do,让当前用户暂时以管理员的身份root来执行这条命令. su是用来改变当前用户的,su root,就是将当前用户切换为root,用了su ...
- 使用多字节字符集的跨平台(PC、Android、IOS、WP)编码/解码方法
随着移动端的发展,跨平台已成为通讯架构设计的重要考虑因素,PC.Android.IOS.WP等跨多平台间的数据通讯,必然要解决字符编码/解码的问题. 多字节字符集MBCS不是跨平台的首选字符集,面向跨 ...
- Oracle 10g如何对用户姓名,按首字母排序、查询
首先介绍Oracle 9i新增加的一个系统自带的排序函数 1.按首字母排序 在oracle9i中新增了按照拼音.部首.笔画排序功能.设置NLS_SORT值 SCHINESE_RADICA ...
- QT类之------QLabel
QLabel 类代表标签,它是一个用于显示文本或图像的窗口部件. 构造 QLabel 类支持以下构造函数: [plain] view plaincopy QLabel(QWidget *parent ...