tl;dr; It's not a competition! I'm just comparing Go and Python. So I can learn Go.
So recently I've been trying to learn Go. It's a modern programming language that started at Google but has very little to do with Google except that some of its core contributors are staff at Google.
The true strength of Go is that it's succinct and minimalistic and fast. It's not a scripting language like Python or Ruby but lots of people write scripts with it. It's growing in popularity with systems people but web developers like me have started to pay attention too.
The best way to learn a language is to do something with it. Build something. However, I don't disagree with that but I just felt I needed to cover the basics first and instead of taking notes I decided to learn by comparing it to something I know well, Python. I did this a zillion years ago when I tried to learn ZPT by comparing it DTML which I already knew well.
My free time is very limited so I'm taking things by small careful baby steps. I read through An Introduction to Programming in Go by Caleb Doxey in a couple of afternoons and then I decided to spend a couple of minutes every day with each chapter and implement something from that book and compare it to how you'd do it in Python.
I also added some slightly more full examples, Markdownserver which was fun because it showed that a simple Go HTTP server that does something can be 10 times faster than the Python equivalent.
What I've learned
-
Go is very unforgiving but I kinda like it. It's like Python but with pyflakes switched on all the time.
-
Go is much more verbose than Python. It just takes so much more lines to say the same thing.
-
Goroutines are awesome. They're a million times easier to grok than Python's myriad of similar solutions.
-
In Python, the ability to write to a list and it automatically expanding at will is awesome.
-
Go doesn't have the concept of "truthy" which I already miss. I.e. in Python you can convert a list type to boolean and the language does this automatically by checking if the length of the list is 0.
-
Go gives you very few choices (e.g. there's only one type of loop and it's the
for
loop) but you often have a choice to pass a copy of an object or to pass a pointer. Those are different things but sometimes I feel like the computer could/should figure it out for me. -
I love the little
defer
thing which means I can put "things to do when you're done" right underneath the thing I'm doing. In Python you get thesetry: ...20 lines... finally: ...now it's over...
things. -
The coding style rules are very different but in Go it's a no brainer because you basically don't have any choices. I like that. You just have to remember to use gofmt.
-
Everything about Go and Go tools follow the strict UNIX pattern to not output anything unless things go bad. I like that.
-
godoc.org is awesome. If you ever wonder how a built in package works you can just type it in after
godoc.org
like this godoc.org/math for example. -
You don't have to compile your Go code to run it. You can simply type
go run mycode.go
it automatically compiles it and then runs it. And it's super fast. -
go get
can take a url likegithub.com/russross/blackfriday
and just install it. No PyPI equivalent. But it scares me to depend on peoples master branches in GitHub. What if master is very different when I go get something locally compared to when I run go get weeks/months later on the server?
UPDATE
Here's a similar project comparing Python vs. JavaScript by Ilya V. Schurov
Comments
Post your own commentFor versioning dependencies check out gopkg.in
Thanks!
I had no idea about this. I haven't read it yet but skimming it lightly it seems like there *is* a solution.
Please find this program .. may be this will be the solution....These are related to map reduce ....
import MapReduce
import sys
"""
Word Count Example in the Simple Python MapReduce Framework
"""
mr = MapReduce.MapReduce()
# =============================
# Do not modify above this line
def mapper(record):
# key: document identifier
# value: document contents
trim_nucleotid = record[1][:-10]
mr.emit_intermediate(trim_nucleotid, 1 )
def reducer(trim_nucleotid, list_of_values):
# key: word
# value: list of occurrence counts
#mr.emit((person,len(list_of_values)) )
mr.emit(trim_nucleotid)
# Do not modify below this line
# =============================
if __name__ == '__main__':
inputdata = open(sys.argv[1])
mr.e xecute(inputdata, mapper, reducer)
What is this related to?
You might want to look into gopkg.in and/or vendoring when it comes to managing external dependencies.
Some package managers https://code.google.com/p/go-wiki/wiki/PackageManagementTools
Great article
That's amazing! That there are so many already.
Packaging a hard thing to get right. It's not hard like brain surgery but it's hard as like in carpentry.
I haven't tried Go yet so thanks for the summary of your experience.
I'm not convinced there's a strong use case for "defer" as I'd think if the block of code is large enough that a finally clause is "too far down" then it's already overly complex and using "defer" repeatedly throughout would make it worse. I could be convinced otherwise.
That said, you could easily make a Python context manager with similar semantics. You'd do "with deferred() as x:" and then could have x.defer(func, *args) throughout, and it would work in similar fashion at the end of the block. Might be useful some day.
Actually, I'm going to change my mind already. In some cases you have to set up a whole series of things, but in the finally clause you can't blindly tear down each of them. You need to check whether the code got to the setup (or raised an exception beforehand). The defer approach does seem like it would simplify that case as you could dispense with a bunch of conditionals in the finally clause. Hmmm... (goes to find code where this may be cleaner)
Yeah, a context manager and its __exit__ is maybe a good alternative to the `finally:` but it's a mess. I loooove Python but let's admit; Go wins this round :)
I don't agree. Perhaps it was different in 2014-10, but contextlib.contextmanager makes it now quite simple to use a with statement. The only drawback I see is the extra indent, but in the end it is not that significant I find.
And godoc -http=:8080 is even cooler … simply open http://localhost:8080/pkg/, and you get the documentation for builtin packages like math, external like github.com/russross/blackfriday and $GOPATH/yourcoolstuff in one place, linked nicely :)
That's neat! That's basically what godoc.org is plus your own $GOPATH stuff.
Same exact thing on python can be done by `pydoc -p 8080`
Interesting. I also really wanted to like go but the language feels so unexpressive and weak when compared to python (interface{} anyone? No operator overloading? Return value as exception?)
I got much happier after trying out rust, proving that new languages don't have to feel awkward and tedious to use.
As someone who has used a multitude of languages ranging from FORTRAN to C/C++/Objective-C to C# to Java to Smalltalk and Python, I do not feel limited in Go with respect to expressiveness. Language design is always a balance between power and simplicity, and I've explored both ends of the spectrum. I'll take the simpler languages (such as Go, Python and Smalltalk) any day. Funnily, I've never used operator overloading and I don't miss it one iota. And there are pros and cons to using exceptions. I like the simplicity of Go's error handling.
Thanks for this super-concise summary! I have a similar take on it:
http://blog.v-studios.com/2014/09/wading-into-go.html
The main thing I'm missing, since I am doing a bunch of work with AWS, is something as mature as Boto. There are a number of "goaws" libraries that are interrelated forks, and some others, but nothing with the features of Boto... yet.
"I can only hope that the Go community likes Belgian beer and single malt whisky as much as the Python community. :-)"
Yeah. That's crucial. Only time will tell.
I am currently learning Go coming from a C, Scheme, C#, Julia and Python background and I can say I am liking Go so far. I would like to correct you on your assertion that Go only has for loops. Go only has for loops token-wise but syntactically for has multiple uses. You can write it like in C, as a while loop and I am not yet sure about the foreach format but I will look it up.
Thanks. I've only ever seen `for` to start a loop. No `while` or `do while`. I haven't seen the foreach thing yet.
For loop is used instead of any loop but foreach. Range substitutes foreach. Have a look at for loop you will see.
Just a little self-promotion you may find interesting. I built goless at PyCon last year, which provides go-like semantics for writing concurrent programs in Python. https://github.com/rgalanakis/goless Maybe it helps scratch an itch and keep you in Python land.
That. Is awesome. I tried to soak in the examples so that when I have a need I'll remember that it's been done there.
You can install python packages from git directly as well
pip install git+ssh://git@github.com/my-user/my-repo.git
i think that there might be a way to install a particular commit / branch as well, although i've never done that
You can. I only know how to do it for an archive. E.g.
pip install https://github.com/rhelmer/pyinotify/archive/9ff352f.zip#egg=pyinotify
> try: ...20 lines... finally: ...now it's over..
In python you have with statement, which is clearly better: defer will only work after function return, while using with you can be sure actions are done after leaving with block.
Oh man. I just looked over your whole list of py vs. go example codes. I dunno how aesthetic wasn't mentioned!
I've been using go just because I'm pretty sure it's going to replace most modern languages in my life, but when it comes to comparing how the two languages read, python hands down. Go has some of the ugliest looking code I've ever seen. And nothing is ever that obvious about what it's doing. Granted, I'll get used to it, it still wastes tons of precious cognitive processing on damn near everything it does.
Still, it has pointers and go routines, so I'm sold. I just wish it wasn't so ugly.
I mean, I get it. "fmt" is what prints the line. I'm glad I get to say that explicitly. But the day I decide to use something else, I'm probably going to want to use it all the way throughout, and then what? I have to replace "fmt" everywhere it is. And I'll probably never need anything else, so it's all the more reason "fmt.println" sucks.
If go just had the ability to allow "fmt" to define "print" as "put the following into fmt.println()", it would clean the code up immensely. There could even be a little golang.list_used_keywords(). So you could check what keywords were being used.
Or something. The point I'm trying to get at is Go is great in terms of functionality, but lacks form. And this is the future, we can do both now. As long as we keep doing one over the other, we'll never stop being the apes of yesterday.
Hello Peter,
I need some advice, I build a program in vb.net (Yes that is still a language).
It uses a lot of timers in it. Example:
timerTEST.interval = 1000 '(Miliseconds)
timerTEST.start
TimerTEST.DoSomething()
Now I'm searching for what programming language I should convert to, so that my program can be used cross-platform.
I'm stuck between GO and Python. Can you give a example which basically does the same as the above mentioned code?
It'd be great if you could do that in both languages. Thanks for the brief explanation. But I'm still stuck :p
Sorry for my English, I'm not a native speaker.
Best regards,
berm
Already there http://govspy.peterbe.com/#time_elapsed
Haha, awesome! Thanks!
Hi Peter, First off, Thanks for the great writeup. I myself have been coding in python for over 7 years now and trying to learn and switch to go. I also think python code is much compact than go like list and dictionary comprehensions and lambda anonymous function. Also, I am a little spectacle about installing dependencies, even though I read somewhere that distribution in go is much easier than in python as it creates a single binary.
Package cx_freeze makes stanalone python programs to you get a folder with dependecy and a exe file, nothing about python have to be install att target machine, i use this a lot to distribute my python programs to production.
Hi,
I'm a network engineer who has rarely had to script or program. I'm trying to learn a programming / scripting language and have begun some online Python courses and bought a couple of books.
After reading this I'm wondering if I should focus on go instead of Python. Any sage advice for a programming novice?
Thanks !
The advantage with Go is that finished programs are faster. But they take longer to write. So pick based on that "metric".
Python it is. Thanks
start to learn go, struggling.
python is easy to learn to use.
For my purposes anyway, until the Go standard library includes tools for parsing arbitrary well-formed XML it wont be able to replace Python.
Thanks for sharing your thoughts. It's a very useful summary.
One thing I can't let go: saying python is a scripting language technically isn't necessary true; in most practical implementation (Cpython, pypy) it's at least compiled to byte code and only then interpreted. Being a dynamically typed language python enables more complex OO programming than known from Cpp or even java.
I was hoping to see an explanation of each language rather than a list of beneficial details. Namely, "use Python if your goal is ____", "use Go if your goal is ____", i.e. reasons to use each tool -- each language's purpose, so to speak. Presently I'm thinking Go is for multiple people writing a program (i.e. code can be written in modules, sections) to be executed by multiple computers, whereas Python is for one person's scientific data analysis and programs to be run by a single computer. Would you agree with this characterization?
The best part about Go is to deal with concurrent program and faster. So if you involved in concurrent program, it's a good choice. But since it's more like C program, also there are a lot of limitation compared with Python to do data analysis. however, it really depends upon what you want to do, then decide what language to choose.
I was surprised at how slow the Go implementation of your webserver was, until I noticed you weren't using KeepAlive. When I turned that on (via -k to the ab tool), the Go implementation ran about 4x faster. The tornado implementation ran about 1.5x faster, and flask ran about the same.
Without KeepAlive, each request creates a new TCP connection, so a lot of extra time gets spent in the kernel. Presumably that's about the same amount of overhead for all of the implementations, so it's better to factor it out.
I would have tested the nodejs version you mentioned, but you didn't include the source. Although you did include source for a falcon-based implementation, so maybe that's what you actually tested instead of nodejs? The performance I saw of falcon vs. the others would fit the same relative results you got with "Node (express)".
Here are the results I got: https://gist.github.com/mhrivnak/b63230b64477798ee787ed5563afc2a2
Thanks for the comparison!
Update! I found the nodejs source in your git repo and updated my Gist with test results from it. I'll file an issue in the repo for the lack of nodejs source on the main post.
I've never seen try/finally used to mimic defer. The idiomatic python solution is a with block, a.k.a. a context manager, which I argue is superior to go's defer since you can achieve the deferral on the same line you're opening the file.
with open("defer.py") as f:
f.read()