My feelings about Go after spending a weekend together

TLDR;

I had a great weekend following the Learn Go with Tests online book. I spent about 15 hours going through the whole book and fire up a few practice projects.

I know it’s not a lot to come to a conclusion, but I had enough experience with other languages to find the pros and cons of the language. As we all know, the biggest and most exciting features of Go area the goroutines and channels. It’s built for concurrency and it’s so stupid simple to work with it.

Go comes with its own little problems. You need to pass Context around, down to the deepest of your call stack. At the time of this post, Go doesn’t have generics, it’s on the way though. Check out the last blog post about it on Golang blog for yourself. Don’t get excited about the syntax though…

// Print prints the elements of any slice.
// Print has a type parameter T and has a single (non-type)
// parameter s which is a slice of that type parameter.
func Print[T interface{}](s []T) {
	// same as above
}

What’s the fuss about the syntax?

I’m a JavaScript developer who switched from C, Java, C#, PHP languages in this particular order. If you ever worked with those languages – and I bet you did -, then you know the drill:

type variableName = value;

function functionName(MyType $val) {}

public static void main(String[] args) {}

You know, going left to right. Type to variable name. Then Go comes to the show and…

func SayHelloToThePeople(people []Person) (hellos []string) {}

Left to right, then right to left. Like, what in the name of Gopher is happening here?

I guess you get it now

Maybe the problem lies in me, I should’ve gone down the route of exotic languages rather than the mainstream ones.

After all, as a full-time JS developer, I’m not sure if these two languages can live together in one muscle. As you get used to writing out type variableName then suddenly switching to variableName []type really twitches my muscle memories. Practice makes perfect though.

Simplicity of Go

Did you know Go only has 25 keywords? We got 32 in C, 54 in Java, 54 in PHP, 59 in JavaScript, and 102 in C#. That’s according to a mid-2017 reddit post. God knows how many keywords now C# got… Anyway, I was lazy to look it up on my own so probably those numbers are off – according to my one minute Google research C# only got 79 keywords. You still get the point, right? Go has few keywords and they managed to stuff the magic of Go – concurrency – into those few keywords.

Let’s talk about the included batteries, in my opinion that’s still something that belongs to the simplicity section. Go comes with all the fun stuff without any external dependencies. Let’s see what we got here:

  • Code formatting (gofmt)
  • Code linting (golint)
  • More code static checks (go vet)
  • Tests (go test)
  • Test coverage (go test -cover, go test -coverprofile=coverprofile.out, go tool cover)
  • An awesome standard library

If you are just starting with Go then you probably don’t need to do anything other than just installing Go. That’s a huge plus for me. Whenever I fire up a new JS project I need to go through setting up a linter, a formatter, a test runner, and many many dependencies (depends on the project though).

I’m sure you are familiar with this

Our modern world of programming is very bloated I must say. I miss the good old days of just putting together a few PHP files and uploading them via FTP.

What’s next?

Well, Go 2 is coming and I’m thrilled but scared at the same time. Hopefully Go 2 will follow what Go 1 started.

Let’s hope this won’t happen. Source: Reddit

I’m hoping for the best regarding the future of Go. I love the current state of the language and I’ll probably continue learning it and putting together a few projects with it.

JavaScript index-naming-hell, what is it and how to avoid it

I used to fall into the same trap…

screenshot of Visusal Studio Code with many index.tsx files open
Look at all those index files

This is how it looks like in the explorer

This works great and in practice it’s easy to use. You can just do

import MyComponent from './components/MyComponent

but when you are editing them in your editor it’s ugly and takes up too much space. It also wrecks quick file navigation since all your files are named… guess what – index.

In this case it’s fine to add some redundancy. If your component is called BirthdayItem, then feel free to rename all your files to BirthdayItem with the proper extension then create an index file that exports your component. So you don’t need to

import MyComponent from './components/MyComponent/MyComponent

Let’s see how it looks in action:

A lot better, now you can actually see what you are editing
Explorer is clean as well

As you can see both the open editors and explorer is a lot more readable. Quick file search also reacts better and easier to find what you are looking for.

Now let’s talk about Intellisense. Whenever I type BirthdayList, VS Code wants to import it from ./components/BirthdayList/BirthdayList. Before the restructure it imported it from the directory like this ./components/BirthdayList. You can clearly see that the latter is the better one. You might think about using the following code and you will get the bad result – just like me.

export { default } from "./BirthdayList";

How do we fix this? In my codebases I try to avoid export default as much as possible. So you can either do it by importing then reexporting as default, like this:

import BirthdayList from "./BirthdayList";
export default BirthdayList;

But as I said, I’d rather avoid export default at all costs:

import BirthdayList from "./BirthdayList";
export { BirthdayList };

This way you will get awesome autocompletion and auto imports without the filename.

Linting markdown files using Node.js

Install dependencies

# Yarn
yarn add -D markdownlint markdownlint-cli2

# NPM
npm install -D markdownlint markdownlint-cli2

Add script to your package.json

"lint:md": "markdownlint-cli2 README.md"

Feel free to replace README.md with any files/globs that you want to lint

Using it with Prettier

Install dependencies

# Yarn
yarn add -D prettier

# NPM
npm install -D prettier

Update your script

"lint:md": "prettier --check README.md && markdownlint-cli2 README.md"

If you have long lines then you might find that Prettier doesn’t error, but markdownlint does. You can either disable line-height rule in markdown lint or enable prose-wrap in your Prettier configuration. You can do this by adding the following part to your package.json

"prettier": {
  "proseWrap": "always"
},

Linting package.json using Node.js

Install dependencies

# Yarn
yarn add -D npm-package-json-lint npm-package-json-lint-config-default

# NPM
npm install -D npm-package-json-lint npm-package-json-lint-config-default

Configure npm-package-json-lint by adding it to your package.json

"npmpackagejsonlint": {
  "extends": "npm-package-json-lint-config-default"
}

Add script to your package.json

"lint:package": "npmPkgJsonLint ."

Check with Prettier

Install dependencies

# Yarn
yarn add -D prettier

# NPM
npm install -D prettier

Include Prettier check in your script

"lint:package": "prettier --check package.json && npmPkgJsonLint ."

Linting CSS in Create React App project

Install dependencies

# Yarn
yarn add -D stylelint stylelint-config-standard

# NPM
npm install -D stylelint stylelint-config-standard

Configure your stylelint

"stylelint": {
  "extends": [
    "stylelint-config-standard"
  ]
}

Add script to your package.json

"lint:css": "stylelint src/**/*.css"

Stylelint with Prettier

Install dependencies

# Yarn
yarn add -D stylelint-prettier stylelint-config-prettier

# NPM
npm install -D stylelint-prettier stylelint-config-prettier

Configure your stylelint with prettier rules

"stylelint": {
  "extends": [
    "stylelint-config-standard",
    "stylelint-prettier/recommended"
  ]
}

Setting up Prettier for Create React App

Install dependencies

# Yarn
yarn add -D prettier eslint-config-prettier eslint-plugin-prettier

# NPM
npm install -D prettier eslint-config-prettier eslint-plugin-prettier

By default your eslintConfig looks like this:

  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  }

Let’s add Prettier and Prettier React to the extends array:

"eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest",
      "plugin:prettier/recommended",
      "prettier/react"
    ]
}

Your editor should pick up the eslint config change after saving package.json. Let’s add two scripts to our package.json, one for formatting and one for linting.

"format:js": "prettier --write src/**/*.{js,jsx,ts,tsx}",
"lint:js": "eslint src/**/*.{js,jsx,ts,tsx}"

(NOTE: I used js,jsx,ts,tsx in the patterns above. If you don’t have any files that match any of those patterns, then you will get an error. Feel free to remove extensions that you aren’t using)

If you are using TypeScript then you might want to add type checking to the lint script as well:

"lint:js": "tsc --noEmit && eslint src/**/*.{js,jsx,ts,tsx}"

Automagically lint before git commit

You might want to automatically run the lint script before git commits. This can be achieved easily by using husky and lint-staged. Let’s start by installing them as dev dependencies:

# Yarn
yarn add -D husky lint-staged

# NPM
npm install -D husky lint-staged

Next you just need to add a few lines to your package.json:

  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "src/**/*.{js,jsx,ts,tsx}": [
      "yarn lint:js"
    ]
  }