DEV Community

Discussion on: My reflections on Golang

Collapse
 
deepu105 profile image
Deepu K Sasidharan

Thanks for the detailed response. Most of my opinion is based on the real-world experience of building a CLI app using Go for the past 9+ months. It's not a super complex app but of fairly medium complexity.

I do some "real-world" project in Java, Ruby, TypeScript (nodeJs) and Go, and Golang structure wasn't particularly complex. There is no reason for your Go structure to be more complex than a POJO for instance. If you have to deal with complex Json, you may use json.Marshaler or json.Unmarshaler interface, like here.

In the beginning, we had some structs that were quite painful on the eye when parsing YAML. We then changed our model to simplify it. I agree you can get complex structures in every language but in Go, it looks a bit more ugly than others IMO. This is purely a personal view, you might find it beautiful. Also, regardless of what parser you use, if you have to transform the data you will end up using structs which looks really complex unless you have control over the data format.

Hmm. Yes, and then ? It means that you may use an instance of your type as an instance of "someone's interface" only if you want, by passing it as a parameter of a function that explicitly ask for "someone's interface" for exemple. I don't see a use case when you may have an unwanted edge case with this feature.

I just stated a fact as I really don't like implicit stuff again a personal preference.

Wrong. The content of maps and slices aren't passed by reference. Slice and Maps are references (default value is nil for them) see. It is something to know, that's true, but this is less confusing than Java primitive type behavior.

Yes, I didn't form that sentence correctly. I'll correct. They are references. But is still confusing, the same way Java primitives are.

You are right. Even with module, dependency management in Golang is much basic than what you can find with npm or maven.
But you miss something important here. Even with big size project, you don't need a lot of dependencies. Unit tests ? All included. Web server ? Maybe a (small) router for dynamic route, and one for secure token if you need, but no more. Database access ? Only the driver. Linter and code inspection ? All included... Such limited dependency manager is consistent with one of the language principle : use the standard library the most (here an example).

I disagree. Yes, there is a lot of standard stuff provided but it's not enough unless you are building something simple. For my medium complex project, we have 31 direct dependencies(Including one for asserts, the default way of asserting in test sucks). Look at some of the popular OSS projects like kubectl etc, they have a lot of dependencies as well. For simple stuff, you can do that without any dependencies in any language if you ok to write verbose code same way you would do in Go. Also using libraries in other languages also is a choice to reduce boilerplate. I have used NPM, yarn, Maven, Gradle, Pip, Gem and so on and If I have to rate the user experience then Go is still at the last

DRY is not related to your complaints. The DRY principle is about bad business logic duplication. For instance, if you have in a bank system, two 90% identical functions to compute account balance, there is chance to have a DRY violation. Here, you are pointing out that Go do not have a lot of syntactic sugar (you are right) and have some idioms that are very C-like (and not so fun). I agree with that. But I think go approach is better for maintenance.

May be but still, I cringe every time I have to duplicate a function and just change a type. I don't know why having Generics is bad? it's 2019.

Yes, I completely agree that Go has the best learning curve among modern languages(It took me just a few hours to start writing code for my application). Even easier than JavaScript I would say. It may be great for newcomers but once you learn it it's a bit annoying. I expect a high-level language to make my work as easy as possible with as less boilerplate possible. I don't want to implement a file walker or web server every time, I just want to use a library and get the job done as fast as possible. SO as I said this is my personal opinion based on my personal preference and I still don't see me writing a complex web application in Go.

But it's ok if you disagree. That's why we have options so you can choose what you like and I can choose what I like :)

Collapse
 
jeromedoucet profile image
jerome DOUCET • Edited

but in Go, it looks a bit more ugly than others IMO

This is weird. On many aspect Go may look different from language like Java or Javascript. But it is very similar on that point.

Is

type Car struct {
  Name        string
  PlateNumber string
}

Really uglier or different than :

public class car {

  private string name;
  private string plateNumber

  // java accessor boilerplate....

}

I just stated a fact as I really don't like implicit stuff again a personal preference.

Fair enough

we have 31 direct dependencies

For one "fairly medium complexity" app ? You should have special needs (a glue app ? integration with a lot of tools), or maybe, you keep habits from other language that doesn't fit much Go. Go isn't Javascript. Most of the time you don't need much dependencies. You maybe don't like how go standard lib will solve a problem, but that's another point.

Including one for asserts, the default way of asserting in test sucks

That is wrong and a little bit arrogant. You don't like it, that's ok, but it doesn't sucks at all. I think you don't understand it.

First of all, I know some smart test lib too like Rspec, Mockito, AssertJ, junit (of course !), chai, karma, jest, etc... There are great ! And when I start to use Golang, I found confusing not having all the syntactic sugar I was accustomed... I found using mock unconvenient and strange that no assertion where available.

Then I become to realize that assertions are not so superior to a simple if... Every developer is able to understand the meaning of a simple "if"... That's no the case with all assertion lib (rspec for example is powerful, but do has his own learning steep).

But mock where still unconvenient, and hard to deals with, 'till I realize what was wrong. I was wrong. It was so easy to inject mock with Rails or Spring, that I didn't see the lack of values of this tests and how poor were some design choices. The need for mocks was just the symptom of a bad design :(.

Go testing package is not a shinny one, but it could help to write better tests, better code.

OSS projects like kubectl etc, they have a lot of dependencies as well

Well, that always far less that what node could require for a simple web app. But yes, go mod was necessary because it was one of the biggest weakness of the language

don't know why having Generics is bad

I never say that Generics are bad, but unrelated to DRY. By the way, lack of generics support is a weakness of the language. It may be useful in some cases.

I don't want to implement a file walker or web server every time

oO ?

// content of index.js
const http = require('http')
const port = 3000

const requestHandler = (request, response) => {
  console.log(request.url)
  response.end('Hello Node.js Server!')
}

const server = http.createServer(requestHandler)

server.listen(port, (err) => {
  if (err) {
    return console.log('something bad happened', err)
  }

  console.log(`server is listening on ${port}`)
})
package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Welcome to my website!")
    })

    http.ListenAndServe(":80", nil)
}

Yes, that's maybe easy as a reply, but http server is not where go has a lot of boilerplate ! With the error system yes (it's true it is verbose).

but once you learn it it's a bit annoying

You hit the point. Go is annoying, because it is very simple. No magic, no shinning thing. And that's exactly what I expect from a language, but this is a personal opinion.

SO as I said this is my personal opinion based on my personal preference and I still don't see me writing a complex web application in Go

But it's ok if you disagree. That's why we have options so you can choose what you like and I can choose what I like

Yes, and I respect your opinion. BUT you decide to expose theses though on a platform that allow comments and discussion, so (respectful) contradictory opinions are part of the game :)

Thread Thread
 
deepu105 profile image
Deepu K Sasidharan

This is weird. On many aspect Go may look different from language like Java or Javascript. But it is very similar on that point.

simpler structs does indeed look fine in Go, as per my original point, they look ugly IMO when there are complex stuff like maps of maps and stuff involved. Again its a personal preference. For the record I also find Java classes ugly :P

For one "fairly medium complexity" app ? You should have special needs (a glue app ? integration with a lot of tools), or maybe, you keep habits from other language that doesn't fit much Go. Go isn't Javascript. Most of the time you don't need much dependencies. You maybe don't like how go standard lib will solve a problem, but that's another point.

I don't agree here, it's not about keeping habits, I don't want to write 10 lines of boilerplate code if a library can do it in 2 line for me. I believe in community/oss and I hate reinventing the wheel. I'm not gonna go into why that approach is better as again its again opinionated.

That is wrong and a little bit arrogant. You don't like it, that's ok, but it doesn't sucks at all. I think you don't understand it.

Sorry if I sounded arrogant, that wasn't the intention. The default way in Go seems to using equals and when having structs and stuff its quite difficult to see what is the difference. Compare the default to github.com/stretchr/testify/assert and you will see what I mean. I want a nice output from my assertion failures.

First of all, I know some smart test lib too like Rspec, Mockito, AssertJ, junit (of course !), chai, karma, jest, etc... There are great ! And when I start to use Golang, I found confusing not having all the syntactic sugar I was accustomed... I found using mock unconvenient and strange that no assertion where available.

Then I become to realize that assertions are not so superior to a simple if... Every developer is able to understand the meaning of a simple "if"... That's no the case with all assertion lib (rspec for example is powerful, but do has his own learning steep).

But mock where still unconvenient, and hard to deals with, 'till I realize what was wrong. I was wrong. It was so easy to inject mock with Rails or Spring, that I didn't see the lack of values of this tests and how poor were some design choices. The need for mocks was just the symptom of a bad design :(.

Go testing package is not a shinny one, but it could help to write better tests, better code.

That's your personal preference. In general, as I stated, again and again, I expect a high-level language to make my work easier. I just don't want to bother about writing if..else for these and wasting my time trying to figure out diff from an assertion failure. Having said that so far I only needed to use an assert lib and not a full-fledged testing framework in Go, whi8ch is quite nice.

Well, that always far less that what node could require for a simple web app. But yes, go mod was necessary because it was one of the biggest weakness of the language

Well, actually you can also do almost everything you can do in Go in Node without using dependencies. Node also has standard libs for almost everything. the reason people end up using so many dependencies is coz they are so super easy to use and reduces boilerplate.

I never say that Generics are bad, but unrelated to DRY. By the way, lack of generics support is a weakness of the language. It may be useful in some cases.

I don't see how it's useful

Yes, that's maybe easy as a reply, but http server is not where go has a lot of boilerplate ! With the error system yes (it's true it is verbose).

fair enough that was a bad example from my side, but I think you get my point

You hit the point. Go is annoying, because it is very simple. No magic, no shinning thing. And that's exactly what I expect from a language, but this is a personal opinion.

Absolutely, and that's my point, I personally prefer a middle ground. I don't like languages bloated with features as well. But Go is too simple for my taste. Maybe once Go has generics I would like it more.

Yes, and I respect your opinion. BUT you decide to expose theses though on a platform that allow comments and discussion, so (respectful) contradictory opinions are part of the game :)

Absolutely, that was the purpose so I can learn other views and may even change my mind on certain points. Thanks for your inputs they are indeed valuable. Another point I was trying to drive home was "using the right tools for the right job"

Thread Thread
 
jeromedoucet profile image
jerome DOUCET • Edited

I don't see how it's useful

I wrote "It may be useful in some cases", "it" referring to Generics. So I guess we agree on this point.

Compare the default to github.com/stretchr/testify/assert and you will see what I mean

I know this lib (using it in the past), and I exactly know what you mean. But I still disagree on this point. Assertion reduce test code verbosity, but doesn't really improve readability. here is an example from one of my pet project. I do not think the usage of assertion will bring a lot of value here.

But the most important is that it is not considered idiomatic to do so in Go. Some articles on the subject here and here.

That's precisely the reason why I still use assertion in Javascript, Java or Ruby, event if I don't find them useful as much as I used to.

Thanks for your inputs they are indeed valuable

Thank you too :)

using the right tools for the right job

I definitely agree with that sentence. And my reaction is mainly drive by the will to show that Go may be a good choice for a web application. It is very opinionated and may look ugly, but is eventually very effective and productive in that use case.

With it's GC and embedded Runtime, Go is more closed to many web-backend plateform than it looks like on the first sight :).

Thread Thread
 
deepu105 profile image
Deepu K Sasidharan

I was talking about the readability of the error messages printed during assert failures. The default way is not very readable whereas this lib provides a nice view with a diff, which IMO is really useful to spot issues.

I would still be open to building web backends for microservices using Go, but for full-fledged real-world web apps how would you handle stuff like security, filters, etc, etc(say stuff provided by spring framework). I have to agree maybe I might be more open if I see a real example of that.

For example, I was thinking about doing a version of JHipster app in Go but then wasn't sure it's worth the effort

Thread Thread
 
jeromedoucet profile image
jerome DOUCET • Edited

There is two possibilities here.

The first is to used the (very good) lib gorilla which provide a full featured http router with many security options (secured cookies, sessions, CSRF protection, etc...). Not the option I prefers, but a very convenient and common one. If you wish to support Go with JHispster, this is the way to follow I guess.

The second is to use the basic http router and to choose the lib you want to use (JsonWebToken, CSRF, etc ...) for security.
The http package is build in a way that make trivial to create filters (by chaining http.Handler or http.HandlerFunc).
I prefers using that way because I prefer to add explicitly security layers.

For SQL injection, the sql package provide automatically a protection against it, as long as you use parameterized requests with Exec() or Query().

You may notice that I am not against the use of dependencies :). Cryptographie and security are domains where I want to rely on a maintained, specialized libs.