美好或者丑陋的 Go 已翻译 100%

oschina 投递于 2018/04/13 16:55 (共 52 段, 翻译完成于 04-18)
阅读 7968
收藏 89
Go
4
加载中

This is an additional post in the “Go is not good” series. Go does have some nice features, hence the “The Good” part in this post, but overall I find it cumbersome and painful to use when we go beyond API or network servers (which is what it was designed for) and use it for business domain logic. But even for network programming, it has a lot of gotchas both in its design and implementation that make it dangerous under an apparent simplicity.

What motivated this post is that I recently came back to using Go for a side project. I used Go extensively in my previous job to write a network proxy (both http and raw tcp) for a SaaS service. The network part was rather pleasant (I was also discovering the language), but the accounting and billing part that came with it was painful. As my side project was a simple API I thought using Go would be the right tool to get the job done quickly, but as we know many projects grow beyond their initial scope, so I had to write some data processing to compute statistics and the pains of Go came back. So here's my take on Go woes.

已有 1 人翻译此段
我来翻译

Some background: I love statically typed languages. My first significant programs were written in Pascal. I then used Ada and C/C++ when I started working in the early 90's. I later moved to Java and finally Scala (with some Go in between) and recently started learning Rust. I've also written a substantial amount of JavaScript, because up to recently it was the only language available in web browsers. I feel insecure with dynamically typed languages and try to limit their use to simple scripting. I'm comfortable with imperative, functional and object oriented approaches.

已有 1 人翻译此段
我来翻译

The Good

Go is easy to learn

That's a fact: if you know any kind of programming language, you can learn most of Go's syntax in a couple of hours with the "Tour of Go", and write your first real program in a couple of days. Read and digest Effective Go, wander around in the standard library, play with a web toolkit like Gorillaor Go kit and you'll be a pretty decent Go developer.

This is because Go's overarching goal is simplicity. When I started learning Go it reminded me when I first discovered Java: a simple language and a rich but not bloated standard library. Learning Go was a refreshing experience coming from today's Java heavy environment. Because of Go's simplicity, Go programs are very readable, even if error handling adds quite some noise (more on this below).

But this may be false simplicity though. Quoting Rob Pike, simplicity is complicated, and we will see below that behind it there are a lot of gotchas waiting to bite us, and that simplicity and minimalism prevent writing DRY code.

已有 1 人翻译此段
我来翻译

Easy concurrent programming with goroutines and channels

Goroutines are probably the best feature of Go. They're lightweight computation threads, distinct from operating system threads.

When a Go program executes what looks like a blocking I/O operation, the Go runtime actually suspends the goroutine and resumes it when an event indicates that some result is available. In the meantime other goroutines have been scheduled for execution. We therefore have the scalability benefits of asynchronous programming with a synchronous programming model.

Goroutines are also lightweight: their stack grows and shrinks on demand, which means having 100s or even 1000s of goroutines is not a problem.

已有 1 人翻译此段
我来翻译

I once had a goroutine leak in an application: these goroutines were waiting for a channel to be closed before ending, and that channel was never closed (a common deadlock issue). The process was eating 90% of the CPU for no reason, and inspecting expvars showed 600k idle goroutines! I guess the CPU was used by the goroutine scheduler.

Sure, an actor system like Akka can handle millions of actors without a sweat, in part because actors don't have a stack, but they're far from being as easy to use as goroutines to write heavily concurrent request/response applications (i.e. http APIs).

Channels are how goroutines should communicate: they provide a convenient programming model to send and receive data between goroutines without having to rely on fragile low level synchronization primitives. Channels come with their own set of usage patterns.

已有 1 人翻译此段
我来翻译

Channels have to be thought out carefully though, as incorrectly sized channels (they're unbuffered by default) can lead to deadlocks. We will also see below that using channels doesn't prevent race conditions because Go lacks immutability.

Great standard library

The Go standard library is really great, particularly for everything related to network protocols or API development: http client and server, crypto, archive formats, compressions, sending email, etc. There's even an html parser and a rather powerful templating engine to produce text & html with automatic escaping to avoid XSS (used for example by Hugo).

已有 1 人翻译此段
我来翻译

The various APIs are generally simple and easy to understand. They can sometimes look simplistic though: this is in part because the goroutine programming model means we just have to care about "seemingly synchronous" operations. This is also because a few versatile functions can also replace a lot of specialized ones as I found out recently for time calculations.

Go is performant

Go compiles to a native executable. Many users of Go come from Python, Ruby or Node.js. For them, this is a mind-blowing experience as they see a huge increase in the number concurrent requests a server can handle. This is actually pretty normal when you come from interpreted languages with either no concurrency (Node.js) or a global interpreter lock. Combined to the language simplicity, this explains part of the excitement for Go.

已有 1 人翻译此段
我来翻译

Compared to Java however, things are not so clear in raw performance benchmarks. Where Go beats Java though, is on memory usage and garbage collection.

Go's garbage collector is designed to prioritize latency and avoid stop-the-world pauses, which is particularly important in servers. This may come with a higher CPU cost, but in a horizontally scalable architecture this is easily solved by adding more machines. Remember that Go was designed at Google, who are all but short on resources!

Compared to Java, the Go GC also has less work to do: a slice of structs is a contiguous array of structures, and not an array of pointers like in Java. Similarly Go maps use small arrays as bucketsfor the same purpose. This means less work for the GC, and also better CPU cache locality.

Go also beats Java for command-line utilities: being a native executable, a Go program has no startup cost contrarily to Java that first has to load and compile bytecode.

已有 1 人翻译此段
我来翻译

Language defined source code format

Some of the most heated debates in my career happened around the definition of a code format for the team. Go solves this by defining a canonical format for Go code. The gofmt tool reformats your code and has no options.

Like it or not, gofmt defines how Go code should be formatted and that problem is therefore solved once for all!

Standardized test framework

Go comes with a great test framework in its standard library. It has support for parallel testing, benchmarks, and contains a lot of utilities to easily test network clients and servers.

已有 1 人翻译此段
我来翻译
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(10)

账户已经注销
账户已经注销
依赖管理问题, 数据结构还是太少,缺乏企业级框架(Java这方面好的不要太多),但是啊,多范式,静态编译,灵活&高效。关键还有几个大佬级别的人物牵头,还有Google这样口碑良好的公司Support,这语言还有很长的路要走,但势头很好。: )
sunnyregion
sunnyregion
go是我目前使用的最爽的语言
osc_179535
osc_179535
用了3年多golang,感觉在做基础框架上确实非常好用且高效,不用像其他语言一样需要费很大的劲才能实现,golang天生就支持一些常用的服务;
不好的地方是,感觉不太适合写业务代码,动态更新方面不是很成熟.
屮殖
屮殖
看进度条以为不长。。。
OSC_UtuypB
OSC_UtuypB
我很讨厌GOPATH
GunsNRose
GunsNRose
好文章
fotomxq
fotomxq
有些缺陷确实说的很正确,应该慢慢去完善和通过三方库补充
S
Schr0dingerCat
go meitian douyao bei hei ji ci
p
partcoes
hei ji ci 啥意思😂
随风巽
随风巽
消灭零回复
返回顶部
顶部