{"id":10536,"date":"2021-03-03T08:00:04","date_gmt":"2021-03-03T16:00:04","guid":{"rendered":"http:\/\/softwareengineeringdaily.com\/?p=10536"},"modified":"2021-03-02T14:49:02","modified_gmt":"2021-03-02T22:49:02","slug":"why-we-switched-from-python-to-go","status":"publish","type":"post","link":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/","title":{"rendered":"Why We Switched from Python to Go"},"content":{"rendered":"<div class=\"Content__ArticleBody-sc-1hizcm9-0 dpaNQV\">\n<p>Switching to a new language is always a big step, especially when only one of your team members has prior experience with that language. Early this year, we switched\u00a0<a href=\"https:\/\/getstream.io\/\" target=\"_blank\" rel=\"noopener\">Stream\u2019s<\/a>\u00a0primary programming language from Python to Go. This post will explain some of the reasons why we decided to leave Python behind and make the switch to Go. Thanks to\u00a0<a href=\"https:\/\/twitter.com\/frascoapp\" target=\"_blank\" rel=\"noopener\">Ren Sakamoto<\/a>\u00a0for translating\u00a0<a href=\"https:\/\/frasco.io\/why-we-switched-from-python-to-go-19581e27de7c\" target=\"_blank\" rel=\"noopener\">Why we switched from Python to Go into Japanese, \u306a\u305c\u79c1\u9054\u306f Python \u304b\u3089 Go \u306b\u79fb\u884c\u3057\u305f\u306e\u304b<\/a>.<\/p>\n<h2 id=\"reason-performance\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Reason 1 &#8211; Performance<\/h2>\n<p>Go is fast! Go is extremely fast. The performance is similar to that of Java or C++. For our use case, Go is typically 40 times faster than Python. Here\u2019s a small benchmark game comparing\u00a0<a href=\"https:\/\/benchmarksgame-team.pages.debian.net\/benchmarksgame\/fastest\/go-python3.html\" target=\"_blank\" rel=\"noopener\">Go vs Python<\/a>.<\/p>\n<h2 id=\"reason-language-performance-matters\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Reason 2 &#8211; Language Performance Matters<\/h2>\n<p>For many applications, the programming language is simply the glue between the app and the database. The performance of the language itself usually doesn\u2019t matter much. Stream, however, is an\u00a0<a href=\"https:\/\/getstream.io\/#bp\" target=\"_blank\" rel=\"noopener\">API provider<\/a>\u00a0powering a\u00a0<a href=\"https:\/\/getstream.io\/activity-feeds\/\" target=\"_blank\" rel=\"noopener\">feeds<\/a>\u00a0and\u00a0<a href=\"https:\/\/getstream.io\/chat\/\" target=\"_blank\" rel=\"noopener\">chat platform<\/a>\u00a0for 700 companies and more than 500 million end users. We\u2019ve been optimizing Cassandra, PostgreSQL, Redis, etc. for years, but eventually, you reach the limits of the language you\u2019re using. Python is a great language but its performance is pretty sluggish for use cases such as serialization\/deserialization, ranking and aggregation. We frequently ran into performance issues where Cassandra would take 1ms to retrieve the data and Python would spend the next 10ms turning it into objects.<\/p>\n<h2 id=\"reason-developer-productivity-not-getting-too-creative\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Reason 3 &#8211; Developer Productivity &amp; Not Getting Too Creative<\/h2>\n<p>Have a look at this little snippet of Go code from the\u00a0<a href=\"http:\/\/howistart.org\/posts\/go\/1\/\" target=\"_blank\" rel=\"noopener\">How I Start Go tutorial<\/a>. (This is a great tutorial and a good starting point to pick up a bit of Go.)<\/p>\n<div>\n<div id=\"gist105392890\" class=\"gist\">\n<div class=\"gist-file\">\n<div class=\"gist-data\">\n<div class=\"js-gist-file-update-container js-task-list-container file-box\">\n<div id=\"file-1-go\" class=\"file my-2\"><\/div>\n<\/div>\n<\/div>\n<div class=\"gist-meta\"><a href=\"http:\/\/https:\/\/gist.github.com\/nparsons08\/3d8df4a4706e131b36afa57e46497934\/raw\/7db57ca9fcf6adfd32c309a62eb73be1188a0308\/1.go\"><img fetchpriority=\"high\" decoding=\"async\" data-attachment-id=\"10539\" data-permalink=\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/1go\/\" data-orig-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/1go.png?fit=1516%2C922&amp;ssl=1\" data-orig-size=\"1516,922\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"1go\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/1go.png?fit=300%2C182&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/1go.png?fit=1024%2C623&amp;ssl=1\" class=\"aligncenter wp-image-10539\" src=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/1go.png?resize=500%2C304\" alt=\"\" width=\"500\" height=\"304\" srcset=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/1go.png?resize=300%2C182&amp;ssl=1 300w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/1go.png?resize=1024%2C623&amp;ssl=1 1024w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/1go.png?resize=768%2C467&amp;ssl=1 768w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/1go.png?w=1516&amp;ssl=1 1516w\" sizes=\"(max-width: 500px) 100vw, 500px\" data-recalc-dims=\"1\" \/><\/a><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>If you\u2019re new to Go, there\u2019s not much that will surprise you when reading that little code snippet. It showcases multiple assignments, data structures, pointers, formatting and a built-in HTTP library. When I first started programming I always loved using Python\u2019s more advanced features. Python allows you to get pretty creative with the code you\u2019re writing. For instance, you can:<\/p>\n<ul>\n<li>Use MetaClasses to self-register classes upon code initialization<\/li>\n<li>Swap out True and False<\/li>\n<li>Add functions to the list of built-in functions<\/li>\n<li>Overload operators via magic methods<\/li>\n<li>Use functions as properties via the @property decorator<\/li>\n<\/ul>\n<p>These features are fun to play around with but, as most programmers will agree, they often make the code harder to understand when reading someone else\u2019s work. Go forces you to stick to the basics. This makes it very easy to read anyone\u2019s code and immediately understand what\u2019s going on.\u00a0<em>Note: How \u201ceasy\u201d it is really depends on your use case, of course. If you want to create a basic CRUD API I\u2019d still recommend Django +<\/em>\u00a0<a href=\"http:\/\/www.django-rest-framework.org\/\" target=\"_blank\" rel=\"noopener\"><em>DRF<\/em><\/a><em>, or Rails.<\/em><\/p>\n<h2 id=\"reason-concurrency-channels\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Reason 4 &#8211; Concurrency &amp; Channels<\/h2>\n<p>As a language, Go tries to keep things simple. It doesn\u2019t introduce many new concepts. The focus is on creating a simple language that is incredibly fast and easy to work with. The only area where it does get innovative is goroutines and channels. (To be 100% correct the concept of\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Communicating_sequential_processes\" target=\"_blank\" rel=\"noopener\">CSP<\/a> started in 1977, so this innovation is more of a new approach to an old idea.) Goroutines are Go\u2019s lightweight approach to threading, and channels are the preferred way to communicate between goroutines. Goroutines are very cheap to create and only take a few KBs of additional memory. Because Goroutines are so light, it is possible to have hundreds or even thousands of them running at the same time. You can communicate between goroutines using channels. The Go runtime handles all the complexity. The goroutines and channel-based approach to concurrency makes it very easy to use all available CPU cores and handle concurrent IO &#8211; all without complicating development. Compared to Python\/Java, running a function on a goroutine requires minimal boilerplate code. You simply prepend the function call with the keyword \u201cgo\u201d:<\/p>\n<div>\n<div id=\"gist105392900\" class=\"gist\">\n<div class=\"gist-file\">\n<div class=\"gist-meta\"><a href=\"http:\/\/https:\/\/gist.github.com\/nparsons08\/6233539067ea11d75febb8978099040e\/raw\/96eb6098c9ddce0070db130a6fb345e66ab0b334\/2.go\"><img decoding=\"async\" data-attachment-id=\"10538\" data-permalink=\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/2go\/\" data-orig-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/2go.png?fit=1516%2C758&amp;ssl=1\" data-orig-size=\"1516,758\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"2go\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/2go.png?fit=300%2C150&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/2go.png?fit=1024%2C512&amp;ssl=1\" class=\"aligncenter wp-image-10538\" src=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/2go.png?resize=500%2C250\" alt=\"\" width=\"500\" height=\"250\" srcset=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/2go.png?resize=300%2C150&amp;ssl=1 300w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/2go.png?resize=1024%2C512&amp;ssl=1 1024w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/2go.png?resize=768%2C384&amp;ssl=1 768w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/2go.png?resize=260%2C129&amp;ssl=1 260w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/2go.png?w=1516&amp;ssl=1 1516w\" sizes=\"(max-width: 500px) 100vw, 500px\" data-recalc-dims=\"1\" \/><\/a><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p><a href=\"https:\/\/tour.golang.org\/concurrency\/1\" target=\"_blank\" rel=\"noopener\">https:\/\/tour.golang.org\/concurrency\/1<\/a>\u00a0Go\u2019s approach to concurrency is very easy to work with. It\u2019s an interesting approach compared to Node where the developer has to pay close attention to how asynchronous code is handled. Another great aspect of concurrency in Go is the\u00a0<a href=\"https:\/\/blog.golang.org\/race-detector\" target=\"_blank\" rel=\"noopener\">race detector<\/a>. This makes it easy to figure out if there are any race conditions within your asynchronous code.<\/p>\n<blockquote><p>Knock knock Race condition Who&#8217;s there?<\/p>\n<p>\u2014 I Am Devloper (@iamdevloper)\u00a0<a href=\"https:\/\/twitter.com\/iamdevloper\/status\/399991896862638081?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">November 11, 2013<\/a><\/p><\/blockquote>\n<p>Here are a few good resources to get started with Go and channels:<\/p>\n<ul>\n<li><a href=\"https:\/\/gobyexample.com\/channels\" target=\"_blank\" rel=\"noopener\">https:\/\/gobyexample.com\/channels<\/a><\/li>\n<li><a href=\"https:\/\/tour.golang.org\/concurrency\/2\" target=\"_blank\" rel=\"noopener\">https:\/\/tour.golang.org\/concurrency\/2<\/a><\/li>\n<li><a href=\"http:\/\/guzalexander.com\/2013\/12\/06\/golang-channels-tutorial.html\" target=\"_blank\" rel=\"noopener\">http:\/\/guzalexander.com\/2013\/12\/06\/golang-channels-tutorial.html<\/a><\/li>\n<li><a href=\"https:\/\/www.golang-book.com\/books\/intro\/10\" target=\"_blank\" rel=\"noopener\">https:\/\/www.golang-book.com\/books\/intro\/10<\/a><\/li>\n<li><a href=\"https:\/\/www.goinggo.net\/2014\/02\/the-nature-of-channels-in-go.html\" target=\"_blank\" rel=\"noopener\">https:\/\/www.goinggo.net\/2014\/02\/the-nature-of-channels-in-go.html<\/a><\/li>\n<li><a href=\"https:\/\/softwareengineering.stackexchange.com\/questions\/222642\/are-go-langs-goroutine-pools-just-green-threads\" target=\"_blank\" rel=\"noopener\">Goroutines vs Green threads<\/a><\/li>\n<\/ul>\n<h2 id=\"reason-concurrency-channels\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Reason 5 &#8211; Fast Compile Time<\/h2>\n<p>Our largest micro service written in Go currently takes 4 seconds to compile. Go\u2019s fast compile times are a major productivity win compared to languages like Java and C++ which are famous for sluggish compilation speed. I like sword fighting, but it\u2019s even nicer to get things done while I still remember what the code is supposed to do:<\/p>\n<p><img decoding=\"async\" data-attachment-id=\"10542\" data-permalink=\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/compilingcode\/\" data-orig-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/CompilingCode.png?fit=1536%2C1339&amp;ssl=1\" data-orig-size=\"1536,1339\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"CompilingCode\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/CompilingCode.png?fit=300%2C262&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/CompilingCode.png?fit=1024%2C893&amp;ssl=1\" class=\"aligncenter wp-image-10542\" src=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/CompilingCode.png?resize=500%2C436\" alt=\"\" width=\"500\" height=\"436\" srcset=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/CompilingCode.png?resize=300%2C262&amp;ssl=1 300w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/CompilingCode.png?resize=1024%2C893&amp;ssl=1 1024w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/CompilingCode.png?resize=768%2C670&amp;ssl=1 768w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/CompilingCode.png?w=1536&amp;ssl=1 1536w\" sizes=\"(max-width: 500px) 100vw, 500px\" data-recalc-dims=\"1\" \/><\/p>\n<h2 id=\"reason-the-ability-to-build-a-team\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Reason 6 &#8211; The Ability to Build a Team<\/h2>\n<p>First of all, let\u2019s start with the obvious: there are not as many Go developers compared to older languages like C++ and Java. According to\u00a0<a href=\"https:\/\/insights.stackoverflow.com\/survey\/2017\" target=\"_blank\" rel=\"noopener\">StackOverflow<\/a>,\u00a0<strong>38%<\/strong>\u00a0of developers know Java,\u00a0<strong>19.3%<\/strong>\u00a0know C++ and only\u00a0<strong>4.6%<\/strong>\u00a0know Go.\u00a0<a href=\"https:\/\/madnight.github.io\/githut\/\" target=\"_blank\" rel=\"noopener\">GitHub data<\/a>\u00a0shows a\u00a0<a href=\"http:\/\/githut.info\/\" target=\"_blank\" rel=\"noopener\">similar trend<\/a>: Go is more widely used than languages such as Erlang, Scala and Elixir, but less popular than Java and C++. Fortunately, Go is a very simple and easy to learn language. It provides the basic features you need and nothing else. The new concepts it introduces are the \u201c<a href=\"https:\/\/blog.golang.org\/defer-panic-and-recover\" target=\"_blank\" rel=\"noopener\">defer<\/a>\u201d statement and built-in management of concurrency with \u201cgo routines\u201d and channels. (For the purists: Go isn\u2019t the first language to implement these concepts, just the first to make them popular.) Any Python, Elixir, C++, Scala or Java dev that joins a team can be effective at Go within a month because of its simplicity. We\u2019ve found it easier to build a team of Go developers compared to many other languages. If you\u2019re hiring people in competitive ecosystems like\u00a0<a href=\"https:\/\/getstream.io\/team\/\" target=\"_blank\" rel=\"noopener\">Boulder and Amsterdam<\/a>\u00a0this is an important benefit.<\/p>\n<h2 id=\"reason-strong-ecosystem\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Reason 7 &#8211; Strong Ecosystem<\/h2>\n<p>For a team of our size (~20 people) the ecosystem matters. You simply can\u2019t create value for your customers if you have to reinvent every little piece of functionality. Go has great support for the tools we use. Solid libraries were already available for Redis, RabbitMQ, PostgreSQL, Template parsing, Task scheduling, Expression parsing and RocksDB. Go\u2019s ecosystem is a major win compared to other newer languages like Rust or Elixir. It\u2019s of course not as good as languages like Java, Python or Node, but it\u2019s solid and for many basic needs you\u2019ll find high-quality packages already available.<\/p>\n<h2 id=\"reason-gofmt-enforced-code-formatting\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Reason 8 &#8211; Gofmt, Enforced Code Formatting<\/h2>\n<p>Let\u2019s start with what is Gofmt? And no, it\u2019s not a swear word. Gofmt is an awesome command line utility, built into the Go compiler for formatting your code. In terms of functionality it&#8217;s very similar to Python\u2019s autopep8. While the show Silicon Valley portrays otherwise, most of us don\u2019t really like to argue about tabs vs spaces. It\u2019s important that formatting is consistent, but the actual formatting standard doesn\u2019t really matter all that much. Gofmt avoids all of this discussion by having one official way to format your code.<\/p>\n<h2 id=\"reason-grpc-and-protocol-buffers\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Reason 9 &#8211; gRPC and Protocol Buffers<\/h2>\n<p>Go has first-class support for protocol buffers and gRPC. These two tools work very well together for building microservices which need to communicate via RPC. You only need to write a manifest where you define the RPC calls that can be made and what arguments they take. Both server and client code are then automatically generated from this manifest. This resulting code is both fast, has a very small network footprint and is easy to use. From the same manifest, you can generate client code for many different languages even, such as C++, Java, Python and Ruby. So, no more ambiguous REST endpoints for internal traffic, that you have to write almost the same client and server code for every time. .<\/p>\n<h2 id=\"reason-fast-compile-time\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Disadvantage 1 &#8211; Lack of Frameworks<\/h2>\n<p>Go doesn\u2019t have a single dominant framework like Rails for Ruby, Django for Python or Laravel for PHP. This is a topic of heated debate within the Go community, as many people advocate that you shouldn\u2019t use a framework to begin with. I totally agree that this is true for some use cases. However, if someone wants to build a simple CRUD API they will have a much easier time with Django\/DJRF, Rails Laravel or\u00a0<a href=\"http:\/\/phoenixframework.org\/\" target=\"_blank\" rel=\"noopener\">Phoenix<\/a>.\u00a0<em>Update:<\/em>\u00a0as the comments pointed out there are several projects that provide a framework for Go.\u00a0<a href=\"https:\/\/github.com\/revel\/revel\" target=\"_blank\" rel=\"noopener\">Revel<\/a>,\u00a0<a href=\"https:\/\/iris-go.com\/\" target=\"_blank\" rel=\"noopener\">Iris<\/a>,\u00a0<a href=\"https:\/\/github.com\/labstack\/echo\" target=\"_blank\" rel=\"noopener\">Echo<\/a>,\u00a0<a href=\"https:\/\/github.com\/go-macaron\/macaron\" target=\"_blank\" rel=\"noopener\">Macaron<\/a>\u00a0and\u00a0<a href=\"https:\/\/github.com\/gobuffalo\/buffalo\" target=\"_blank\" rel=\"noopener\">Buffalo<\/a>\u00a0seem to be the leading contenders. For Stream&#8217;s use case we prefer to not use a framework. However for many new projects that are looking to provide a simple CRUD API the lack of a dominant framework will be a serious disadvantage.<\/p>\n<h2 id=\"disadvantage-error-handling\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Disadvantage 2 &#8211; Error Handling<\/h2>\n<p>Go handles errors by simply returning an error from a function and expecting your calling code to handle the error (or to return it up the calling stack). While this approach works, it\u2019s easy to lose scope of what went wrong to ensure you can provide a meaningful error to your users. The\u00a0<a href=\"https:\/\/github.com\/pkg\/errors\" target=\"_blank\" rel=\"noopener\">errors package<\/a>\u00a0solves this problem by allowing you to add context and a stack trace to your errors. Another issue is that it\u2019s easy to forget to handle an error by accident. Static analysis tools like errcheck and megacheck are handy to avoid making these mistakes. While these workarounds work well it doesn\u2019t feel quite right. You\u2019d expect proper error handling to be supported by the language.<\/p>\n<h2 id=\"reason-the-ability-to-build-a-team\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Disadvantage 3 &#8211; Package Management<\/h2>\n<p><em>Update: Go&#8217;s package management has come a long way since this post was written.\u00a0<a href=\"https:\/\/blog.golang.org\/using-go-modules\" target=\"_blank\" rel=\"noopener\">Go modules<\/a>\u00a0are an effective solution, the only issue I&#8217;ve seen with them is that they break some static analysis tools like errcheck. Here&#8217;s a tutorial for learning to use\u00a0<a href=\"https:\/\/getstream.io\/blog\/go-1-11-rocket-tutorial\/\" target=\"_blank\" rel=\"noopener\">Go using Go modules<\/a>.\u00a0\u00a0<\/em>\u00a0Go\u2019s package management is by no means perfect. By default, it doesn\u2019t have a way to specify a specific version of a dependency and there\u2019s no way to create reproducible builds. Python, Node and Ruby all have better systems for package management. However, with the right tools, Go\u2019s package management works quite well. You can use\u00a0<a href=\"https:\/\/insights.stackoverflow.com\/survey\/2017\" target=\"_blank\" rel=\"noopener\">Dep<\/a>\u00a0to manage your dependencies to allow specifying and pinning versions. Apart from that, we\u2019ve contributed an open-source tool called\u00a0<a href=\"https:\/\/github.com\/getstream\/vg\" target=\"_blank\" rel=\"noopener\">VirtualGo<\/a>\u00a0which makes it easier to work on multiple projects written in Go.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"10541\" data-permalink=\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/virtualstream\/\" data-orig-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/VirtualStream.png?fit=1536%2C1567&amp;ssl=1\" data-orig-size=\"1536,1567\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"VirtualStream\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/VirtualStream.png?fit=294%2C300&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/VirtualStream.png?fit=1004%2C1024&amp;ssl=1\" class=\"aligncenter wp-image-10541\" src=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/VirtualStream.png?resize=500%2C510\" alt=\"\" width=\"500\" height=\"510\" srcset=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/VirtualStream.png?resize=294%2C300&amp;ssl=1 294w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/VirtualStream.png?resize=1004%2C1024&amp;ssl=1 1004w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/VirtualStream.png?resize=768%2C784&amp;ssl=1 768w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/VirtualStream.png?resize=1506%2C1536&amp;ssl=1 1506w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/VirtualStream.png?w=1536&amp;ssl=1 1536w\" sizes=\"(max-width: 500px) 100vw, 500px\" data-recalc-dims=\"1\" \/><\/p>\n<h2 id=\"reason-strong-ecosystem\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Python vs Go<\/h2>\n<p><em>Update: The performance difference between Python and Go increased since this post was written. (Go became faster and Python didn&#8217;t)<\/em>\u00a0One interesting experiment we conducted was taking our\u00a0<a href=\"https:\/\/getstream.io\/docs\/#custom_ranking\" target=\"_blank\" rel=\"noopener\">ranked feed<\/a>\u00a0functionality in Python and rewriting it in Go. Have a look at this example of a ranking method:<\/p>\n<div>\n<div id=\"gist105392909\" class=\"gist\">\n<div class=\"gist-file\">\n<div class=\"gist-data\">\n<div class=\"js-gist-file-update-container js-task-list-container file-box\">\n<div id=\"file-3-json\" class=\"file my-2\"><\/div>\n<\/div>\n<\/div>\n<div class=\"gist-meta\"><a href=\"http:\/\/https:\/\/gist.github.com\/nparsons08\/1c2fa6c29ce0d3e61fface0a30c831fe\/raw\/6489f90a1bf1ae82e51864849a29f1f538375f78\/3.json\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"10537\" data-permalink=\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/3json\/\" data-orig-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/3json.png?fit=1524%2C978&amp;ssl=1\" data-orig-size=\"1524,978\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"3json\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/3json.png?fit=300%2C193&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/3json.png?fit=1024%2C657&amp;ssl=1\" class=\"aligncenter wp-image-10537\" src=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/3json.png?resize=500%2C321\" alt=\"\" width=\"500\" height=\"321\" srcset=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/3json.png?resize=300%2C193&amp;ssl=1 300w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/3json.png?resize=1024%2C657&amp;ssl=1 1024w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/3json.png?resize=768%2C493&amp;ssl=1 768w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/3json.png?w=1524&amp;ssl=1 1524w\" sizes=\"(max-width: 500px) 100vw, 500px\" data-recalc-dims=\"1\" \/><\/a><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Both the Python and Go code need to do the following to support this ranking method:<\/p>\n<ol>\n<li>Parse the expression for the score. In this case, we want to turn this string \u201csimple_gauss(time)*popularity\u201d into a function that takes an activity as input and returns a score as output.<\/li>\n<li>Create partial functions based on the JSON config. For example, we want \u201csimple_gauss\u201d to call \u201cdecay_gauss\u201d with a scale of 5 days, offset of 1 day and a decay factor of 0.3.<\/li>\n<li>Parse the \u201cdefaults\u201d configuration so you have a fallback if a certain field is not defined on an activity.<\/li>\n<li>Use the function from step 1 to score all activities in the feed.<\/li>\n<\/ol>\n<p>Developing the Python version of the ranking code took roughly 3 days. That includes writing the code, unit tests and documentation. Next, we\u2019ve spent approximately 2 weeks optimizing the code. One of the optimizations was translating the score expression (simple_gauss(time)*popularity) into an\u00a0<a href=\"https:\/\/docs.python.org\/3\/library\/ast.html\" target=\"_blank\" rel=\"noopener\">abstract syntax tree<\/a>. We also implemented caching logic which pre-computed the score for certain times in the future. In contrast, developing the Go version of this code took roughly 4 days. The performance didn\u2019t require any further optimization. So while the initial bit of development was faster in Python, the Go based version ultimately required substantially less work from our team. As an added benefit, the Go code performed roughly 40 times faster than our highly-optimized Python code. Now, this is just a single example of the performance gains we\u2019ve experienced by switching to Go. It is, of course, comparing apples to oranges:<\/p>\n<ul>\n<li>The ranking code was my first project in Go<\/li>\n<li>The Go code was built after the Python code, so the use case was better understood<\/li>\n<li>The Go library for expression parsing was of exceptional quality<\/li>\n<\/ul>\n<p>Your mileage will vary. Some other components of our system took substantially more time to build in Go compared to Python. As a general trend, we see that\u00a0<em>developing<\/em>\u00a0Go code takes slightly more effort. However, we spend much less time\u00a0<em>optimizing<\/em>\u00a0the code for performance.<\/p>\n<h2 id=\"reason-gofmt-enforced-code-formatting\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Elixir vs Go &#8211; The Runner Up<\/h2>\n<p>Another language we evaluated is\u00a0<a href=\"https:\/\/elixir-lang.org\/\" target=\"_blank\" rel=\"noopener\">Elixir<\/a>. Elixir is built on top of the Erlang virtual machine. It\u2019s a fascinating language and we considered it since one of our team members has a ton of experience with Erlang. For our use cases, we noticed that Go\u2019s raw performance is much better. Both Go and Elixir will do a great job serving thousands of concurrent requests. However, if you look at individual request performance, Go is substantially faster for our use case. Another reason why we chose Go over Elixir was the ecosystem. For the components we required, Go had more mature libraries whereas, in many cases, the Elixir libraries weren\u2019t ready for production usage. It\u2019s also harder to train\/find developers to work with Elixir. These reasons tipped the balance in favor of Go. The Phoenix framework for Elixir looks awesome though and is definitely worth a look.<\/p>\n<h2 id=\"reason-grpc-and-protocol-buffers\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Conclusion<\/h2>\n<p>Go is a very performant language with great support for concurrency. It is almost as fast as languages like C++ and Java. While it does take a bit more time to build things using Go compared to Python or Ruby, you\u2019ll save a ton of time spent on optimizing the code. We have a small development team at\u00a0<a href=\"https:\/\/getstream.io\/team\/\" target=\"_blank\" rel=\"noopener\">Stream<\/a>\u00a0powering feeds and\u00a0<a href=\"https:\/\/getstream.io\/chat\/\" target=\"_blank\" rel=\"noopener\">chat<\/a>\u00a0for over 500 million end users. Go\u2019s combination of a\u00a0<strong>great ecosystem<\/strong>,\u00a0<strong>easy onboarding<\/strong>\u00a0for new developers,\u00a0<strong>fast performance<\/strong>,\u00a0<strong>solid support<\/strong>\u00a0for concurrency and a\u00a0<strong>productive programming environment<\/strong>\u00a0make it a great choice. Stream still leverages Python for our dashboard, site and machine learning for\u00a0<a href=\"https:\/\/getstream.io\/personalization\" target=\"_blank\" rel=\"noopener\">personalized feeds<\/a>. We won\u2019t be saying goodbye to Python anytime soon, but going forward all performance-intensive code will be written in Go. Our new\u00a0<a href=\"https:\/\/getstream.io\/chat\/#chatmessaging\" target=\"_blank\" rel=\"noopener\">Chat API<\/a>\u00a0is also written entirely in Go. If you want to learn more about Go check out the blog posts listed below. To learn more about Stream,\u00a0<a href=\"https:\/\/getstream.io\/get_started\/\" target=\"_blank\" rel=\"noopener\">this interactive tutorial<\/a>\u00a0is a great starting point.<\/p>\n<h2 id=\"disadvantage-lack-of-frameworks\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">More Reading about Switching to Golang<\/h2>\n<ul>\n<li><a href=\"https:\/\/movio.co\/en\/blog\/migrate-Scala-to-Go\/\" target=\"_blank\" rel=\"noopener\">https:\/\/movio.co\/en\/blog\/migrate-Scala-to-Go\/<\/a><\/li>\n<li><a href=\"https:\/\/hackernoon.com\/why-i-love-golang-90085898b4f7\" target=\"_blank\" rel=\"noopener\">https:\/\/hackernoon.com\/why-i-love-golang-90085898b4f7<\/a><\/li>\n<li><a href=\"https:\/\/sendgrid.com\/blog\/convince-company-go-golang\/\" target=\"_blank\" rel=\"noopener\">https:\/\/sendgrid.com\/blog\/convince-company-go-golang\/<\/a><\/li>\n<li><a href=\"https:\/\/dave.cheney.net\/2017\/03\/20\/why-go\" target=\"_blank\" rel=\"noopener\">https:\/\/dave.cheney.net\/2017\/03\/20\/why-go<\/a><\/li>\n<\/ul>\n<h2 id=\"disadvantage-error-handling\" class=\"Heading__Root-gyf2pd-0 jrXbjp\">Learning Go<\/h2>\n<ul>\n<li><a href=\"https:\/\/learnxinyminutes.com\/docs\/go\/\" target=\"_blank\" rel=\"noopener\">https:\/\/learnxinyminutes.com\/docs\/go\/<\/a><\/li>\n<li><a href=\"https:\/\/tour.golang.org\/\" target=\"_blank\" rel=\"noopener\">https:\/\/tour.golang.org\/<\/a><\/li>\n<li><a href=\"http:\/\/howistart.org\/posts\/go\/1\/\" target=\"_blank\" rel=\"noopener\">http:\/\/howistart.org\/posts\/go\/1\/<\/a><\/li>\n<li><a href=\"https:\/\/getstream.io\/blog\/building-a-performant-api-using-go-and-cassandra\/\" target=\"_blank\" rel=\"noopener\">https:\/\/getstream.io\/blog\/building-a-performant-api-using-go-and-cassandra\/<\/a><\/li>\n<li><a href=\"https:\/\/www.amazon.com\/gp\/product\/0134190440\" target=\"_blank\" rel=\"noopener\">https:\/\/www.amazon.com\/gp\/product\/0134190440<\/a><\/li>\n<li><a href=\"https:\/\/getstream.io\/blog\/go-1-11-rocket-tutorial\/\" target=\"_blank\" rel=\"noopener\">Go Rocket Tutorial<\/a><\/li>\n<\/ul>\n<\/div>\n<div class=\"ArticleFooter__Root-sc-12x6vdm-0 izPAZ\">\n<div class=\"ArticleFooter__Categories-sc-12x6vdm-1 dhdgcY\">#engineering #go<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Switching to a new language is always a big step, especially when only one of your team members has prior experience with that language. Early this year, we switched\u00a0Stream\u2019s\u00a0primary programming language from Python to Go. This post will explain some of the reasons why we decided to leave Python behind and make the switch to<\/p>\n","protected":false},"author":63,"featured_media":10540,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Why We Switched from Python to Go by Thierry Schellenbach @tschellenbach @getstream_io","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[1363,83,2143],"tags":[4429,431,128,4428,4430,236,4427],"class_list":["post-10536","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-all-episodes","category-articles","category-exclusive-content","tag-compile-time","tag-elixir","tag-go","tag-goroutines","tag-learning-resources","tag-python","tag-stream"],"jetpack_publicize_connections":[],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.8 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Why We Switched from Python to Go - Software Engineering Daily<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Why We Switched from Python to Go - Software Engineering Daily\" \/>\n<meta property=\"og:description\" content=\"Switching to a new language is always a big step, especially when only one of your team members has prior experience with that language. Early this year, we switched\u00a0Stream\u2019s\u00a0primary programming language from Python to Go. This post will explain some of the reasons why we decided to leave Python behind and make the switch to\" \/>\n<meta property=\"og:url\" content=\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/\" \/>\n<meta property=\"og:site_name\" content=\"Software Engineering Daily\" \/>\n<meta property=\"article:published_time\" content=\"2021-03-03T16:00:04+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-03-02T22:49:02+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/GoCowboy.png?fit=1536%2C847&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"1536\" \/>\n\t<meta property=\"og:image:height\" content=\"847\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Thierry Schellenbach\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@software_daily\" \/>\n<meta name=\"twitter:site\" content=\"@software_daily\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Thierry Schellenbach\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/\"},\"author\":{\"name\":\"Thierry Schellenbach\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/#\/schema\/person\/556db5a19bc3edc67a8b85b60808cfa5\"},\"headline\":\"Why We Switched from Python to Go\",\"datePublished\":\"2021-03-03T16:00:04+00:00\",\"dateModified\":\"2021-03-02T22:49:02+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/\"},\"wordCount\":2576,\"publisher\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/GoCowboy.png?fit=1536%2C847&ssl=1\",\"keywords\":[\"compile time\",\"Elixir\",\"Go\",\"goroutines\",\"learning resources\",\"Python\",\"Stream\"],\"articleSection\":[\"All Content\",\"Exclusive Articles\",\"Exclusive Content\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/\",\"url\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/\",\"name\":\"Why We Switched from Python to Go - Software Engineering Daily\",\"isPartOf\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/GoCowboy.png?fit=1536%2C847&ssl=1\",\"datePublished\":\"2021-03-03T16:00:04+00:00\",\"dateModified\":\"2021-03-02T22:49:02+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#primaryimage\",\"url\":\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/GoCowboy.png?fit=1536%2C847&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/GoCowboy.png?fit=1536%2C847&ssl=1\",\"width\":1536,\"height\":847},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/softwareengineeringdaily.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Why We Switched from Python to Go\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/#website\",\"url\":\"https:\/\/softwareengineeringdaily.com\/\",\"name\":\"Software Engineering Daily\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/softwareengineeringdaily.com\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/#organization\",\"name\":\"Software Engineering Daily\",\"url\":\"https:\/\/softwareengineeringdaily.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2024\/01\/cropped-sed_website_banner.png?fit=549%2C169&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2024\/01\/cropped-sed_website_banner.png?fit=549%2C169&ssl=1\",\"width\":549,\"height\":169,\"caption\":\"Software Engineering Daily\"},\"image\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/software_daily\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/#\/schema\/person\/556db5a19bc3edc67a8b85b60808cfa5\",\"name\":\"Thierry Schellenbach\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/6f63a96982775df26b1f19df57f7c45e?s=96&d=retro&r=pg\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/6f63a96982775df26b1f19df57f7c45e?s=96&d=retro&r=pg\",\"caption\":\"Thierry Schellenbach\"},\"sameAs\":[\"http:\/\/getstream.io\"],\"url\":\"https:\/\/softwareengineeringdaily.com\/author\/stream\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Why We Switched from Python to Go - Software Engineering Daily","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/","og_locale":"en_US","og_type":"article","og_title":"Why We Switched from Python to Go - Software Engineering Daily","og_description":"Switching to a new language is always a big step, especially when only one of your team members has prior experience with that language. Early this year, we switched\u00a0Stream\u2019s\u00a0primary programming language from Python to Go. This post will explain some of the reasons why we decided to leave Python behind and make the switch to","og_url":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/","og_site_name":"Software Engineering Daily","article_published_time":"2021-03-03T16:00:04+00:00","article_modified_time":"2021-03-02T22:49:02+00:00","og_image":[{"width":1536,"height":847,"url":"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/GoCowboy.png?fit=1536%2C847&ssl=1","type":"image\/png"}],"author":"Thierry Schellenbach","twitter_card":"summary_large_image","twitter_creator":"@software_daily","twitter_site":"@software_daily","twitter_misc":{"Written by":"Thierry Schellenbach","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#article","isPartOf":{"@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/"},"author":{"name":"Thierry Schellenbach","@id":"https:\/\/softwareengineeringdaily.com\/#\/schema\/person\/556db5a19bc3edc67a8b85b60808cfa5"},"headline":"Why We Switched from Python to Go","datePublished":"2021-03-03T16:00:04+00:00","dateModified":"2021-03-02T22:49:02+00:00","mainEntityOfPage":{"@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/"},"wordCount":2576,"publisher":{"@id":"https:\/\/softwareengineeringdaily.com\/#organization"},"image":{"@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/GoCowboy.png?fit=1536%2C847&ssl=1","keywords":["compile time","Elixir","Go","goroutines","learning resources","Python","Stream"],"articleSection":["All Content","Exclusive Articles","Exclusive Content"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/","url":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/","name":"Why We Switched from Python to Go - Software Engineering Daily","isPartOf":{"@id":"https:\/\/softwareengineeringdaily.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#primaryimage"},"image":{"@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/GoCowboy.png?fit=1536%2C847&ssl=1","datePublished":"2021-03-03T16:00:04+00:00","dateModified":"2021-03-02T22:49:02+00:00","breadcrumb":{"@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#primaryimage","url":"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/GoCowboy.png?fit=1536%2C847&ssl=1","contentUrl":"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/GoCowboy.png?fit=1536%2C847&ssl=1","width":1536,"height":847},{"@type":"BreadcrumbList","@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/03\/why-we-switched-from-python-to-go\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/softwareengineeringdaily.com\/"},{"@type":"ListItem","position":2,"name":"Why We Switched from Python to Go"}]},{"@type":"WebSite","@id":"https:\/\/softwareengineeringdaily.com\/#website","url":"https:\/\/softwareengineeringdaily.com\/","name":"Software Engineering Daily","description":"","publisher":{"@id":"https:\/\/softwareengineeringdaily.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/softwareengineeringdaily.com\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/softwareengineeringdaily.com\/#organization","name":"Software Engineering Daily","url":"https:\/\/softwareengineeringdaily.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/softwareengineeringdaily.com\/#\/schema\/logo\/image\/","url":"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2024\/01\/cropped-sed_website_banner.png?fit=549%2C169&ssl=1","contentUrl":"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2024\/01\/cropped-sed_website_banner.png?fit=549%2C169&ssl=1","width":549,"height":169,"caption":"Software Engineering Daily"},"image":{"@id":"https:\/\/softwareengineeringdaily.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/software_daily"]},{"@type":"Person","@id":"https:\/\/softwareengineeringdaily.com\/#\/schema\/person\/556db5a19bc3edc67a8b85b60808cfa5","name":"Thierry Schellenbach","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/softwareengineeringdaily.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/6f63a96982775df26b1f19df57f7c45e?s=96&d=retro&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6f63a96982775df26b1f19df57f7c45e?s=96&d=retro&r=pg","caption":"Thierry Schellenbach"},"sameAs":["http:\/\/getstream.io"],"url":"https:\/\/softwareengineeringdaily.com\/author\/stream\/"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/02\/GoCowboy.png?fit=1536%2C847&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/p7GuoD-2JW","_links":{"self":[{"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/posts\/10536"}],"collection":[{"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/users\/63"}],"replies":[{"embeddable":true,"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/comments?post=10536"}],"version-history":[{"count":0,"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/posts\/10536\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/media\/10540"}],"wp:attachment":[{"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/media?parent=10536"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/categories?post=10536"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/tags?post=10536"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}