Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What was it like to learn Go? #1277

Closed
ErikSchierboom opened this issue Oct 3, 2019 · 5 comments
Closed

What was it like to learn Go? #1277

ErikSchierboom opened this issue Oct 3, 2019 · 5 comments
Assignees

Comments

@ErikSchierboom
Copy link
Member

We’ve recently started a project to find the best way to design our tracks, in order to optimize the learning experience of students.

As a first step, we’ll be examining the ways in which languages are unique and the ways in which they are similar. For this, we’d really like to use the knowledge of everyone involved in the Exercism community (students, mentors, maintainers) to answer the following questions:

  1. How was your experience learning Go? What was helpful while learning Go? What did you struggle with? How did you tackle problems?
  2. In what ways did Go differ from other languages you knew at the time? What was hard to learn? What did you have to unlearn? What syntax did you have to remap? What concepts carried over nicely?

Could you spare 5 minutes to help us by answering these questions? It would greatly help us improve the experience students have learning Go :)

Note: this issue is not meant as a discussion, just as a place for people to post their own, personal experiences.

Want to keep your thoughts private but still help? Feel free to email me at erik@exercism.io

Thank you!

@tehsphinx
Copy link
Member

tehsphinx commented Oct 5, 2019

My Background

Before Go I had extensively used VBA/VB.Net, PHP, Javascript/jQuery and Python. VBA mostly while still in school until after university (for about 14 years, not fulltime), VB.Net for roughly 2 years (6 months full time), PHP was part of my tech stack for 8.5 years professionally, Python for 4.5 years (professionally) and JavaScript is still part of my tech stack for 11 years now. Since early 2016 I am mostly programming in Go (professionally and on the side).

Motivation to learn Go

At work we had more than 20 Python servers and needed more performance. The GIL prevented us to use the resources of the hardware. Therefore Concurrency and performance optimisations was what I dug into first.

My experience learning Go

Missing: x, y, z

The first thing I stumbled over (and see most students on exercism and stackoverflow stumble over) was not the new concepts, but the missing ones. Especially from Python I was used to write every bit of code in a way it could be reused. In Go that was suddenly not supported and/or not encouraged.

Missing: Generics

Especially in Python and PHP there is a ready-to-go function for everything. In both languages you can write everything generically and with that create your own tool-kit of more generic functions. Since Go is statically typed and does not have generics (yet), those functions cannot be written generically for all the types a developer can invent (there are ways, but outside of Go's type system). In a sense I had to stop googling and start writing in Go. E.g. checking if an item exists in a slice is a function you just write yourself. Over and over again for the type you need right now. In that context I also had to unlearn the nagging feeling that an existing function would be better because it would be faster -- which I got drummed into myself especially in the Python world: "Your own code is never fastest. Only with special packages and a lot of tricks you can get real speed!"

About writing my own generic functions: It took some time to unlearn the mindset of thinking, duplicating code would be something bad. That often duplicating code is actually speeding up development and making the code easier to maintain in the long run. Exactly the things we as developers want to achieve with generic code is actually often achieved with duplicate code. The mindset of early abstraction does not fit into the Go programming world. (Abstraction is of course possible in Go: see for example Interfaces section)

Missing: Inheritance

Inheritance in Python was a neat way to have multiple classes have a common behaviour that could be overwritten if needed. It quickly became apparent, that Go's composition did not support how I had used inheritance before.

Missing: Function Overloading

Since Go was statically typed which my VB.Net experience was closest to, I quickly looked into function overloading as a means to program more generically. As you can guess: Go does not support that.

Missing: Optional parameters

Optional parameters was something I used a lot in Python. As Go does not support them, I had to come up with other ways of inserting settings into a function or struct (via NewX function).

Generic Data structures

In Javascript I had often used long objects for settings which overwrote another object of default settings. While that is possible in Go with maps one should use structs for settings instead. Also using maps in Go to work with json is tempting but should not be done (use structs). Those are typical examples of trying to work around Go's type system instead of with it.

Concurrency

Concurrency was a new concept to me. I had been working with multiple threads in Python but that was a completely different beast. Starting goroutines is super easy, but how do I manage, synchronize and especially shut them down again? Apart from learning about concurrency patterns in Go, it was also the first time I had to deal with protecting shared memory -- with mutexes, atomic operations or by avoiding shared memory with channels.

There is also the concurrent thinking that needs to be learned. Concurrency is not parallelism! I found that most beginners (including myself) start using goroutines to parallelize things first. The disillusionment happens when they then realize that things are not faster but even slower because they picked the wrong scope to parallelize. Most cpu operations in the real world do not benefit from using multiple cpus. Programming concurrently is so much more than speeding up a single task using multiple cpus.

Channels

Channels are of course another quite unique feature of Go. Buffered, unbuffered, buffered how large? When to use them at all?

Interfaces

The first thing about interfaces I had to realize is that the empty interface{} is not a replacement for generics and should be used extremely rarely.
Next I stumbled into the "trap" of using an interface for "every" (exaggerating!) struct I created. It felt weird quickly because I had to constantly adjust the struct and the interface when a change was needed. It took a while until I learned that the interface should be defined for the usage, not the definition, making them smaller and very powerful. That is also when I finally understood how to write code generically in Go (at least to a certain degree).

Pointers

Last point I want to mention for now: pointers. For me pointers were a new concept I had not used before. Of course I knew what they are but when to use a pointer and when not, which types have pointers under the hood and therefore do not need an additional pointer (in most cases), when to use pointer receivers on functions and when not, etc. was an entirely different thing. I assume that is something even developers coming from C need to adjust to.

Summary

I realized back then and even more today what a fundamental shift in thinking is necessary when learning Go with a similar background as I had. Learning the new stuff was much easier than unlearning the way I had programmed before. Although I think it is a lot easier today as there are much more resources and the community has figured out way more about what idiomatic Go is, than back in early 2016 when I started.

@tehsphinx
Copy link
Member

tehsphinx commented Oct 5, 2019

Error Handling

Another point to add is error handling. Before I was used to have a global handler for exceptions (python) which would then print a stack trace of the exception to be logged to a central ELK stack. Same with PHP errors.
In Go errors are values like any other data and they can be worked with like any other data, too. Any function that can fail returns an error as last argument which should then be handled explicitly by either passing it back up to the next function or handling it.
That needed a bit getting used to and some research on how to get errors into an ELK stack with additional information and with stack traces. Now I wouldn't want to go back to a language that doesn't make me handle errors explicitly, as that improves code quality significantly and makes reading the code a lot easier.

@NobbZ
Copy link
Member

NobbZ commented Nov 1, 2019

How was your experience learning Go? What was helpful while learning Go? What did you struggle with? How did you tackle problems?

I really had a hard time learning go, as I consider its typesystem very restrictive, and I consider its way of error handling a fail (to avoid getting into a rage, I won't elaborate).

Similar to how I did with python, I struggled with mutability everywhere, as a first thing I had to accept.

Syntax itself was quickly to learn though and there weren't any suprises. Also the formatter which is used about everywhere in the community, makes it easy to read foreign code, as at least the layout will be the same everywhere.

In what ways did Go differ from other languages you knew at the time? What was hard to learn? What did you have to unlearn? What syntax did you have to remap? What concepts carried over nicely?

Go definitely differs in its way to handle errors. Errors are returned as a value from a "failable" function and may be either nil or something… In many cases this is all we get, and we can convert this error into a string. Other languages I used, usually provided better tooling around errors or structure to match on. Something that made it easy to decide whether there was a timeout or just bad data from the network.

Also the way how go dealt with packages was different from anything else. In go one just imports a package from its github name (or other supported VCS) and it will be downloaded in its most current version if not currently available locally. This behaviour made it very hard to develop for company and university that time, as both projects required the same library but in different versions. I only learned about verndoring later. Today this shouldn't be a problem anymore, as go modules got pretty much standard in the community, and dependency handling got much closer to how I'm used to it from other languages, a single central source of truth that specifies the dependencies and their versions.

Also go has a limited stack space and doesn't like recursion very much, as I did mainly functional at that time, this was a inconvinience.

@kellydanma
Copy link

kellydanma commented Feb 12, 2020

Background

I'm a junior at university studying Italian, Life sciences, and only recently Computer Science. I did not have many preconceived ideas from other languages, having only used C and Java at school. I started learning Go due to an internship where most of the work was in Go or Perl.

Learning Go

How was your experience learning Go? What was helpful while learning Go? What did you struggle with? How did you tackle problems?

Exercism was my main source of learning, along with Go by Example and Gophercises. The exercises were useful in teaching the fundamentals of software engineering as someone with a limited technical background: error handling, unit testing, interfaces.

I loved gofmt and the clear definition of "best practices" in Go in comparison with other languages, as well as the engaged and active online community. I tackled most of my problems via stackoverflow and discussions with my Exercism mentor, bitfield.

In what ways did Go differ from other languages you knew at the time? What was hard to learn? What did you have to unlearn? What syntax did you have to remap? What concepts carried over nicely?

I didn't have a lot of experience with other languages before learning Go, since I took my first computer science class about 12 months ago (and we learned basic concepts like for-loops in C, only a bit of data structures). I appreciated the C influence on Go since I found OOP difficult to grasp and Java was hard for me to learn.

@ErikSchierboom
Copy link
Member Author

We're closing this issue as it was part of our research for the v3 version of Exercism which has just been released.

Thanks everyone for chipping in! It has been greatly appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants