前言,视频一楼。极客大学go训练营,极客算法训练营,极客python,怎么选择啊?大家现在都学习什么?go简单还是Python简单些?
用 Go 编程的感觉很棒。库程序里有我想要的一切,总体实现较为完善。学习体验也十分顺畅,不得不说,Go 是一种经过精心设计的实用性语言。举个例子:一旦你知悉了 Go 的语法,就能将其他语言中惯用法延续到 Go 中。只要你学会一些 Go,就可以相对轻易地推测 Go 语言的其他特性。凭借一些来自其他语言的知识,我能够阅读并理解 Go 代码,而不需要过多的搜索(Google)。
与 C/C++、Java、Python 等相比,Go 并没有那么多痛点,而且更具生产力。然而,它还是与这些语言处在同一个时代。尽管它从其他语言身上吸取了一些教训,甚至我个人认为它可能是那一代语言中最好的那个,但绝对还属于那一代语言。这是一种渐进式的改进,而不是推陈出新(需要明确的是,这不是意味着对其价值的批判,从软件工程的角度,渐进式改进通常会带来好的影响)。一个很好的例证是 nil:像 Rust 和 Swift 这样的语言已经去除了 null 的概念,并且消除了相关的一整类错误。Go 降低了一部分风险:没有空值(no null values),在 nil 和 0 之间进行区分。但其核心思想仍未改变,同样还会出现解空指针引用这种常见的运行时错误。
易学性
Go 非常易学。我知道人们经常吹捧这一点,但是我真的为自己生产力的飞速提高而感到震惊。多亏了 Go 语言以及它的文档和工具,我仅仅花了两天时间就可以写出「有价值」、可以提交的代码。
有助于易学性的几个因素是:
Go 很精简。很多语言都试图让自己看起来小巧,但 Go 真正做到了这一点(这基本上是一件好事,我对这种自律精神印象深刻)。
标准库很出色(同样,也很小)。从生态系统中寻找并使用库程序非常容易。
几乎没有其他语言中所不具备的东西。Go 从其他既存语言中提取了很多内容,并进行完善,最后将它们很好地组合在一起。它在避免标新立异这一方面做了极大努力。
乏味的样板式代码
Go 代码很快就会变得非常重复。这是由于它缺乏宏或者泛型这种用于减少重复的机制(接口虽然有利于抽象,但在减少代码重复方面作用没有那么大)。最终我会写很多函数,而他们除了类型不同之外其他甚至完全一样。
错误处理也会导致重复。许多函数中像 if err != nil { return err } 这样的样板式代码甚至比那些真正有价值的代码还要多。
使用泛型或宏来减少样板式代码有时会受到批评,理由是不应为使代码易于编写而使其丧失可读性。我发现 Go 恰恰提供了一个反例,复制和粘贴代码往往既快速又简单,阅读代码却会令人灰心丧气,因为你不得不忽略大量的无关代码或者在大量的相同代码中找到细微的不同。
我喜欢的东西
编译时间:绝对快,可以确定要比 Rust 快得多。但实际上,它并没有我预期的那么快(对于中型到大型项目,我感觉它的速度只是与 C/C++ 相接近,或者稍微快一点。而我更加期待能够即时编译)。
协程(goroutine)和信道(channel):值得称赞的是,Go 为生成协程和使用信道提供了轻量级的语法。尽管只是一个小细节,却使 Go 的并发编程体验比其他语言更优越,它真正揭示了语法的力量。
接口:它们并不复杂,但是很容易理解和使用,并且在很多地方都很实用。
if …; … { } 语法:可以将变量的作用域限制在 if 语句真的很好。这与 Swift 及 Rust 中的 if let 起着相似的效果,但用途更为广泛(Go 没有像 Swift 和 Rust 那样的模式匹配,所以它无法使用 if let )。
测试和文档注释都很容易使用。
Go 工具链非常友好:将所有东西都放在一个地方,而不需要在命令行上使用多个工具。
拥有垃圾收集器(GC):不用考虑内存管理真的会使编程更加轻松。
可变参数。
我不喜欢的东西
以下内容没有特定的顺序。
nil切片:要知道 nil、nil 切片和空切片三者都不相同,我敢保证我们只需要其中的两个,而不需要第三个。
枚举类型并不是第一公民:使用常量模拟枚举让人感觉是一种倒退。
不允许循环引用:这实际上限制了包在划分项目模块中的可用性,因为它变相鼓励了在一个包中堆积大量文件(或拥有大量零碎的小包,如果本该放在一起的文件四处分散,这也同样糟糕)。
switch允许出现遗漏匹配的情况。
for … range语句会返回一对「索引/值」。要想只获取索引很容易(忽略值就好);但若要只获取值,则需要显式声明。在我看来,这种做法更应该颠倒过来,因为在大多数情况下,我更需要值而不是索引。
语法:
定义与用途存在不一致。
编译器有时会很挑剔(例如,要求或禁止尾随逗号);通过良好的工具可以缓解这种困扰,但是有时仍然会产生一些恼人的额外步骤。
使用多值返回类型时,类型上需要括号,但 return 语句中却不需要。
声明一个结构体需要两个关键字(type 和 struct)。
采用大写命名法来标记公共或私有变量,看起来就像匈牙利命名法那样,但更糟糕。
隐式接口。我知道它也出现在我喜欢的东西中,但有时候它确实很惹人烦——特别是当你试图找出所有实现该接口的类型,或者哪些接口是为给定类型而实现的时候。
你无法在不同的包中编写带有接收器的函数,所以即使接口是「鸭子类型」的,你也不能为其他包中的类型实现这个接口,这使得它们的用处大大降低。
还有我之前已经提过的,Go 缺少泛型和宏。
一致性
作为一名语言设计者和程序员,Go 最让我惊讶的地方也许是它的内置功能和用户可用功能之间频频出现不一致。许多语言的目标之一就是尽可能消除编译器魔法,让用户也能使用内置功能。运算符重载是一个简单但有争议的例子。但 Go 有很多魔法!你很容易就会遇到这样的问题:无法做那些内置功能可以做的事情。
一些让我印象深刻的地方:
返回多个值和信道的语法很棒,但是这两个无法一起使用,因为没有元组类型。
能够用 for … range 语句对数组和切片进行迭代,但对其他集合就无能为力了,因为它缺乏迭代器的概念。
像 len 或者 append 这样的函数是全局函数,但你自己的函数却无法转变成全局函数。这些全局函数只能使用内置类型。即便 Go「没有泛型」,它们也可以变得通用。
没有运算符重载,那么 == 就会使人感到恼火。因为这意味着你不能在词典中使用自定义类型作为键,除非它们是可比较的。这一属性派生自类型结构,程序员无法重写该属性。
总结
Go 是一种简单、小巧、令人愉悦的语言。它也有一些犄角旮旯,但绝大部分是经过精心设计的。它的学习速度令人难以置信,并且规避了其他语言中一些不那么广为人知的特性。
Go 也是一种与 Rust 截然不同的语言。虽然两者都可以笼统地描述为「系统语言」或「C 语言的替代品」,但它们的设计目标、应用领域、语言风格和优先级不尽相同。垃圾收集确实带来了一个巨大的差异:使用 GC 使得 Go 变得更简单、更小,也更容易理解。而不使用 GC 使 Rust 奇快无比(特别是在您需要保证延迟,而不仅仅是高吞吐量的时候),并且得以支持 Go 中不可能实现的特性或编程模式(或者至少在不牺牲性能的前提下是无法实现的)。
Go 是一种编译型语言,其运行时得到了良好的实现,其速度毋庸置疑。Rust 也是编译型语言,但是运行时要小得多,它真的迅捷无比。在没有其他限制的情况下,我认为选择使用 Go 还是 Rust 其实意味着一种权衡:一方面,Go 的学习曲线更短、程序更简单(这意味着更快的开发速度);另一方面,Rust 真的性能卓越,并且类型系统更富有表现力(这使程序更安全,也意味着更快的调试和错误查找)。
P.S. Nrc 的英文原文可以点击 这里 查看。感谢 Rust 语言社区的小伙伴的翻译和审校(翻译:尚卓燃;审校:吴聪、张汉东)。
P.P.S 如果有知友想通过实战同时学习 Go 语言 + sql 语言以及分布式系统基础知识,可以参加 Talent Plan 动手实现一个 Tinysql,边学边练,亲身体验。
编辑于 2020-05-09
赞同 501
评论 53

玉蛇2020-05-09
嗯,写go的感觉是,不停的处理err,不停的重复写代码
玉蛇2020-05-09
而这个恰恰是最讨厌的,我们都不喜欢做重复的工作
打开 App 查看更多评论
继续浏览内容

知乎
发现更大的世界
打开

UC 浏览器
继续
广告

相关推荐
幸福满满的无骨凤爪来啦!
微博的广告

从 0 学习 Go 语言 - 3 个入门学习网站
登龙的文章 · 5 赞同
Go语言的核心特性有那些?
Davie的回答 · 37 赞同
离婚边缘,该如何挽救婚姻?怎样才是夫妻之间正确的相处之道?


幸福里情感 的广告
查看详情
更多回答

知乎用户
背景
在接触Golang以前,我用C/C++、Lua及Python作为主要开发语言。
C/C++的问题:
开发效率低,对开发者要求高
libc只向后兼容,运维难度偏大
Lua/Python的问题:
动态语言,缺少编译过程,低级错误频出
缺少有效的性能分析及调试工具
场景
当时刚完成了Nginx WAF模块的开发工作,便开始着手搭建WAF的后台管理系统。 由于之前同事都用的fluentd作为日志收集组件,为保持基础组件的一致性,我也选择了fluentd。 即最终架构为fluentd->mongodb->MysqL,再基于MysqL做前端数据展示。 后来被坑了许多次,就决定用Go重写fluentd以解决下面几个问题:
fluentd在ubuntu 9.04偶尔会出现假死,导致数据丢失
fluentd难以接入公司现有的包发布系统,导致运维难度极大
mongodb采用mmap实现,数据量大时占用内存过高
方案
gofluent的代码 请点击这里
httpmq的代码 请点击这里
事实上,这两个项目都是为了解决上面提到的问题。 说起来也许你不信,这两个套代码是我在业余时间完成的,也就是说这根本不算在KPI之内。 其实一开始我也没想到能够这么快就写得七七八八,毕竟是现学现用啊。 但实际情况就是,我花了一周时间写完httpmq,一个月多时间就写好了gofluent……当然,这两个项目还有很多不完善的地方。目前就日志收集方案来说,我更推荐elastic/logstash-forwarder · GitHub和elastic/logstash · GitHub配合使用。
为什么选择Golang
那么,为什么我会选择Golang呢?其实我在做出这个选择之前已经花了大量时间做过详尽调研。 国外如Google、AWS、Cloudflare、CoreOS等,国内如七牛、阿里等都已经开始大规模使用Golang开发其云计算相关产品。 跟着世界级巨人的脚步应该不至于走错方向,而且在学习Golang的过程中,我也渐渐被其背后的设计哲学所折服。
另外,云风博客中曾说过这样一句话:
我发现我花了四年时间锤炼自己用 C 语言构建系统的能力,试图找到一个规范,可以更好的编写软件。结果发现只是对 Go 的模仿。缺乏语言层面的支持,只能是一个拙劣的模仿。
以下则是我对Golang的浅薄理解:
有C基础,学Golang非常轻松
同步方式轻松实现高并发
代码简洁,格式统一,阅读方便
性能强劲的同时,开发效率又不差于Python等动态语言
效果
最开始准备上线的时候其实心里挺忐忑,毕竟一旦出现故障,不仅黑锅得自己背,面子也上过不去啊。 还好结果蛮漂亮,自上线后没出现过一次突发性BUG,降低运维难度的同时还减少了机器的负载。
总而言之,从工程的角度上来看,对于大多数后台应用场景,选择Golang是极为明智的选择。 这样可以很轻松的兼顾运行性能、开发效率及维护难度这三大让诸多程序猿欲仙欲死的奇点。
----------------------- 广告分割线 -------------------------
最近把项目里用到的框架开源出来了,欢迎关注 hnlq715/doggy
App 内查看
赞同 531
评论 45

co lin2015-05-12
关于云风那段话,印象中好像是许式伟说的吧?
知乎用户2015-05-12
哥,read me 那个 text 图用什么画的
打开 App 查看更多评论
继续浏览内容

知乎
发现更大的世界
打开

UC 浏览器
继续

asta谢
成功的习惯比成功更重要
编辑推荐
我尝试来回答你几个问题:
1、Go有什么优势
可直接编译成机器码,不依赖其他库,glibc的版本有一定要求,部署就是扔一个文件上去就完成了。
静态类型语言,但是有动态语言的感觉,静态类型的语言就是可以在编译的时候检查出来隐藏的大多数问题,动态语言的感觉就是有很多的包可以使用,写起来的效率很高。
语言层面支持并发,这个就是Go最大的特色,天生的支持并发,我曾经说过一句话,天生的基因和整容是有区别的,大家一样美丽,但是你喜欢整容的还是天生基因的美丽呢?Go就是基因里面支持的并发,可以充分的利用多核,很容易的使用并发。
内置runtime,支持垃圾回收,这属于动态语言的特性之一吧,虽然目前来说GC不算完美,但是足以应付我们所能遇到的大多数情况,特别是Go1.1之后的GC。
简单易学,Go语言的作者都有C的基因,那么Go自然而然就有了C的基因,那么Go关键字是25个,但是表达能力很强大,几乎支持大多数你在其他语言见过的特性:继承、重载、对象等。
丰富的标准库,Go目前已经内置了大量的库,特别是网络库非常强大,我最爱的也是这部分。
内置强大的工具,Go语言里面内置了很多工具链,最好的应该是gofmt工具,自动化格式化代码,能够让团队review变得如此的简单,代码格式一模一样,想不一样都很困难。
跨平台编译,如果你写的Go代码不包含cgo,那么就可以做到window系统编译linux的应用,如何做到的呢?Go引用了plan9的代码,这就是不依赖系统的信息。
内嵌C支持,前面说了作者是C的作者,所以Go里面也可以直接包含c代码,利用现有的丰富的C库。
2、Go适合用来做什么
服务器编程,以前你如果使用C或者C++做的那些事情,用Go来做很合适,例如处理日志、数据打包、虚拟机处理、文件系统等。
分布式系统,数据库代理器等
网络编程,这一块目前应用最广,包括Web应用、API应用、下载应用、
内存数据库,前一段时间google开发的groupcache,couchbase的部分组建
云平台,目前国外很多云平台在采用Go开发,CloudFoundy的部分组建,前VMare的技术总监自己出来搞的apcera云平台。
3、Go成功的项目
nsq:bitly开源的消息队列系统,性能非常高,目前他们每天处理数十亿条的消息
docker:基于lxc的一个虚拟打包工具,能够实现PAAS平台的组建。
packer:用来生成不同平台的镜像文件,例如VM、vBox、AWS等,作者是vagrant的作者
skynet:分布式调度框架
Doozer:分布式同步工具,类似ZooKeeper
Heka:mazila开源的日志处理系统
cbfs:couchbase开源的分布式文件系统
tsuru:开源的PAAS平台,和SAE实现的功能一模一样
groupcache:memcahe作者写的用于Google下载系统的缓存系统
god:类似redis的缓存系统,但是支持分布式和扩展性
gor:网络流量抓包和重放工具
以下是一些公司,只是一小部分:
http://Apcera.com
http://Stathat.com
Juju at Canonical/Ubuntu, presentation
http://Beachfront.iO at Beachfront Media
CloudFlare
Soundcloud
Mozilla
disqus
http://Bit.ly
Heroku
google
youtube
下面列出来了一些使用的用户
GoUsers - go-wiki - A list of organizations that use Go.
4、Go还存在的缺点
以下缺点是我自己在项目开发中遇到的一些问题:
Go的import包不支持版本,有时候升级容易导致项目不可运行,所以需要自己控制相应的版本信息
Go的goroutine一旦启动之后,不同的goroutine之间切换不是受程序控制,runtime调度的时候,需要严谨的逻辑,不然goroutine休眠,过一段时间逻辑结束了,突然冒出来又执行了,会导致逻辑出错等情况。
GC延迟有点大,我开发的日志系统伤过一次,同时并发很大的情况下,处理很大的日志,GC没有那么快,内存回收不给力,后来经过profile程序改进之后得到了改善。
pkg下面的图片处理库很多bug,还是使用成熟产品好,调用这些成熟库imagemagick的接口比较靠谱
最后还是建议大家学习Go,这门语言真的值得大家好好学习,因为它可以做从底层到前端的任何工作。
学习Go的话欢迎大家通过我写的书来学习,我已经开源在github:
astaxie/build-web-application-with-golang · GitHub
还有如果你用来做API开发或者网络开发,那么我做的开源框架beego也许适合你,可以适当的来学习一下:
astaxie/beego · GitHub
交流群:148647580
Go技术社区:Go 技术社区
App 内查看
赞同 2272
评论 88

新一2013-08-03
赞谢大
知乎用户2013-08-03
很赞,另外不是import不支持版本管理,问题应该是在go get不支持版本管理
打开 App 查看更多评论
继续浏览内容

知乎
发现更大的世界
打开

UC 浏览器
继续

Rio
Python话题下的优秀答主
编辑推荐
知乎大部分项目是 Python 写的,有几个小项目是用 Go 写的。我从一个 Python 为主的开发者的角度说说对 Go 的优点的体会吧:
部署简单。Go 编译生成的是一个静态可执行文件,除了 glibc 外没有其他外部依赖。这让部署变得异常方便:目标机器上只需要一个基础的系统和必要的管理、监控工具,完全不需要操心应用所需的各种包、库的依赖关系,大大减轻了维护的负担。这和 Python 有着巨大的区别。由于历史的原因,Python 的部署工具生态相当混乱【比如 setuptools, distutils, pip, buildout 的不同适用场合以及兼容性问题】。官方 PyPI 源又经常出问题,需要搭建私有镜像,而维护这个镜像又要花费不少时间和精力。
并发性好。Goroutine 和 channel 使得编写高并发的服务端软件变得相当容易,很多情况下完全不需要考虑锁机制以及由此带来的各种问题。单个 Go 应用也能有效的利用多个 cpu 核,并行执行的性能好。这和 Python 也是天壤之比。多线程和多进程的服务端程序编写起来并不简单,而且由于全局锁 GIL 的原因,多线程的 Python 程序并不能有效利用多核,只能用多进程的方式部署;如果用标准库里的 multiprocessing 包又会对监控和管理造成不少的挑战【我们用的 supervisor 管理进程,对 fork 支持不好】。部署 Python 应用的时候通常是每个 cpu 核部署一个应用,这会造成不少资源的浪费,比如假设某个 Python 应用启动后需要占用 100MB 内存,而服务器有 32 个 cpu 核,那么留一个核给系统、运行 31 个应用副本就要浪费 3GB 的内存资源。
良好的语言设计。从学术的角度讲 Go 语言其实非常平庸,不支持许多高级的语言特性;但从工程的角度讲,Go 的设计是非常优秀的:规范足够简单灵活,有其他语言基础的程序员都能迅速上手。更重要的是 Go 自带完善的工具链,大大提高了团队协作的一致性。比如 gofmt 自动排版 Go 代码,很大程度上杜绝了不同人写的代码排版风格不一致的问题。把编辑器配置成在编辑存档的时候自动运行 gofmt,这样在编写代码的时候可以随意摆放位置,存档的时候自动变成正确排版的代码。此外还有 gofix, govet 等非常有用的工具。
执行性能好。虽然不如 C 和 Java,但通常比原生 Python 应用还是高一个数量级的,适合编写一些瓶颈业务。内存占用也非常省。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。