If you have read my first blog Let’s Go, which is not about the Go programming language, go check it out 😅. You can easily tell how much I am obsessed with the Go programming language. After writing my first blog, I have done some thinking, like where to start my Go programming series blog. I have done some research and collected some notes.

As you read the heading of the blog, I will cover some of the basics that I think are important for anyone starting a programming language that also follows some of the principles of clean code. The topics that I have covered in this blog are the effective way you write your Go code and questions that arise in my mind when I have studied Golang, like why there are different types of variable declarations. Why have they created the Go programming language?

Let’s find the answer’s:

History of Go

The Google search engine experienced an issue back in 2007.

  • Programs containing millions of lines of code needed to be maintained.
  • Before they could experiment with any new code changes, they had to compile the program, which took them about an hour at that time.
  • String processing is Google’s additional issue.
  • Numerous text files, or web pages, are read and analyzed by Google.

This was obviously not good for the developers because it made them less productive.

So Google engineers Robert Griesemer, Rob Pike, and Ken Thompson sketched out some goals for a new language:

  • Fast Compilation (Efficiency)
  • Less cumbersome code (Simplicity)
  • Unused memory freed automatically (Garbage Collection)
  • Easy-to-write software that does several operations simultaneously (Concurrency)
  • Good support for processor with multiple cores

After a couple years of work, Google had created Go: a language that was fast to write code and produced programs that were fast to compile and run. Google built a rich library of string functions into Go, Garbage Collecting makes strings in Go simple to think about, and efficient in ways some other string libraries are not. The project switched to an open source license in 2009. It’s now free for anyone to use.

If you’re developing a command-line tool in Go, you can generate executable files for Windows, MacOS, and Linux using the same source code. If you’re building a web server, Go can assist you in efficiently managing multiple simultaneous user connections. Regardless of your project’s nature, Go will aid you in making your code easier to maintain.


Let’s start with syntax and clean code principles :

Go file layout

Now let’s look at the code and figure out what it actually means…


package main

import "fmt"

func main() {
    fmt.Println("Hello, World")
}

Every Go file has three sections:

  1. The package clause
  2. Any import statements
  3. The actual code
  • Package : A package in Go is a way to organize and structure code into meaningful units, helping with code organization and reusability. It allows control over visibility, promoting encapsulation and dependency management. The main package serves as the entry point for Go programs.

  • import : Go files almost always have one or more import statements. The import statement is used to bring in external packages that your code relies on. It ensures that your program loads only the necessary packages, making it faster and more efficient than loading everything at once.

  • actual code : The last part of every Go file is the actual code, which is often split up into one or more functions. A function is a group of code that you call (run) from other places in your program. When a Go program is run, it looks for a function named main and runs that first, which is why we need this function main.

  • Function : A function is a group of one or more lines of code that you can call (run) from other places in your program.

Below is the code with what it does in comments:


// This line says the rest of the code in 
// this file belongs to the "main" package
package main 

// This says we will be using text-formatting
// code from the "fmt" package
import "fmt"

// The "main" function is special; it gets run
// first when your program runs.
func main() {
    // This line displays ("print") "Hello, World" in
    // your terminal (or web browser, if you're using the Go Playground)
    //
    // It does this by calling the "Println" function
    // from the "fmt" package
    fmt.Println("Hello, World")
}

Note: When a Go program is run, it looks for a function named main and runs that first.

No Semicolons

As you can see in our previous program, there are no semicolons to separate statements in Go; we can use semicolons, but it’s not required (in fact, it’s generally frowned upon). This design choice was made to enhance code readability and reduce the potential for common programming errors.

Like C, Go’s formal grammar uses semicolons to terminate statements, but unlike C, those semicolons do not appear in the source. Instead, the lexer uses a simple rule to insert semicolons automatically as it scans, so the input text is mostly free of them.

How does it know when to add semicolons?

The rule is: If a line ends with an identifier (for example: words such as int or float64), a basic value such as a number or a string, or certain specific tokens such as

break continue fallthrough return ++ -- ) }

The Go lexer then adds a semicolon after that token when it encounters a newline, which is \n.

To put it simply, when there’s a chance that a newline could end a statement, Go automatically inserts a semicolon.

One consequence of the semicolon insertion rules is that you cannot put the opening brace of a control structure like if, for, switch, or select on the new line. If you do, a semicolon will be inserted before the brace, which could cause unwanted effects. So write them similar to below:


if i < f() {
    g()
}

not like this:


if i < f()  // wrong!
{           // wrong!
    g()
}

Formatting

Formatting issues are the most contentious but the least important. People may prefer different formatting styles, so when another developer or person reads the same code, it may take some time for them to grasp if they are not accustomed to the same formatting style. It will be easier if everyone formats their documents the same way.

Go takes an unusual approach and lets the machine take care of most formatting issues. The Go compiler comes with a standard formatting tool called go fmt. This tool reads a program and automatically formats it with consistent indentation, alignment, and comment retention or adjustment to match a standard style.

Next time, whenever you share your code, other Go developers will expect it to be in the standard Go format. With Go, all you have to do is run go fmt.

If you want to try its simple version, head over to the Go playground, write some unformatted code, and hit the format button.

Comments

In Go, developers write text annotations within the source code as comments. These annotations are not executed by the program but serve as notes, explanations, or documentation. Comments are essential for providing context, making code more understandable, and documenting code for future reference.

Go provides C-style /* */ block comments and C++-style // line comments.

  1. Single-line comments: Single-line comments start with two slashes // and continue until the end of the line. They are used for adding brief explanations or clarity to a specific line of code.


// This is a single-line comment in Go.
var x int // This comment explains the purpose of the variable.

  1. Multi-line comments: Multi-line comments are enclosed within /* and */ and can span multiple lines. They are commonly used for documenting larger sections of code, writing package-level documentation, or providing more detailed explanations.


/*
This is a multi-line comment in Go.
It can span multiple lines and is useful for providing
detailed explanations or comments for larger code blocks.
*/

Go also has a convention for documenting exported (public) identifiers and packages using special comments, often referred to as “comment annotations” or “comments for the godoc tool”. These comments are structured in a way that allows the godoc tool to automatically generate documentation based on them.

For documenting exported identifiers, you can use a comment placed directly before the identifier, starting with the identifier name and a brief description:



// MyFunction is a public function that performs a specific task.
func MyFunction() {
    // Function implementation...
}

For package-level documentation, you can include a comment at the top of the file:



// Package mypackage provides functionality for...
package mypackage

import "fmt"

// ExportedFunction is a function that...
func ExportedFunction() {
    // Function implementation...
}

To generate documentation from these comments, you can use the godoc command-line tool. Running godoc on your Go code will produce documentation that includes your comments, making it easier for others to understand and use your code. Properly documented code is not only more understandable but also encourages collaboration and code maintenance.

Names

names

Names are as important in Go as in any other language. When coding, we should consider naming variables, functions, arguments, classes, packages, source files, and directories that contain those source files.

According to the book Clean Code by Robert C. Martin, there are some standards for naming:

  1. Choose descriptive and unambiguous names.
  2. Make a meaningful distinction.
  3. Use pronounceable names.
  4. Use searchable names.
  5. Replace magic numbers with named constants.
  6. Avoid encodings. Don’t append prefixes or type information.

You can check this points in detail in this blog

Go has one simple set of rules that apply to the names of variables, functions, and types:

  • A name must begin with a letter and can have any number of additional letters and numbers.
  • The following points determine the visibility of a name (variable, function, and type names) outside a package:
    • If the name of a variable, function, or type begins with a Capital letter, it is considered as Exported and can be accessed from a package outside the current one.
    • Example - As you have seen in the above hello world program. The P in fmt.Println is capitalized: so it can be used from the main package or any other.
    • If the name begins with a Lowercase letter, it is considered Unexported and can only be accessed within the current package.

Above are the only rules that are enforced in Go language. But Go Community follows some additional conventions as well:

  • When naming something in Go, for instance a variable or a function, use CamelCase. This means that if the name has more than one word, start with a lowercase letter for the first word and then capitalize the first letter of each following word without using spaces.
  • For example, topRank and RetryConnection are in CamelCase, which looks like camel humps.
  • If a name’s meaning is clear from the context, it’s common to use abbreviations such as i for index or max for maximum to keep the code concise and easy to read.

MixedCaps

The convention in Go is to use MixedCaps or mixedCaps rather than underscores to write multi-word names.

Package Name

Good package names make code better. A package’s name provides context for its contents, making it easier for the developer or user to understand what the package is for and how to use it. The name also helps package maintainers determine what does and does not belong in the package as it evolves. Well-named packages make it easier to find the code you need.

Package Name Guideline

To make a Go package easy to use, it’s best to give it a short, clear, and meaningful single-word name. Packages typically have lowercase names without under_scores or mixed capital letters. These names are often simple nouns, for example:

  • time (provides functionality for measuring and displaying time)
  • list (implements a doubly linked list)
  • http (provides HTTP client and server implementations)

Below are examples of bad naming styles in Go:

  • computeServiceClient
  • priority_queue

Abbreviate judiciously. Package names may be abbreviated when the abbreviation is familiar to the programmer. Widely used packages often have compressed names:

  • strconv (string conversion)
  • syscall (system call)
  • fmt (formatted I/O)

Note:- If abbreviating a package name makes it ambiguous or unclear, don’t do it.

Another convention is that the package name is the base name of its source directory; the package in src/encoding/base64 is imported as "encoding/base64" but has the name base64, not encoding_base64 and not encodingBase64.

Another short example is once.Do; once.Do(setup) reads well and would not be improved by writing once.DoOrWaitUntilDone(setup). Long names don’t automatically make things more readable. A helpful doc comment can often be more valuable than an extra-long name.

Interface Names

By convention, one-method interfaces are named by the method name plus an -er suffix or similar modification to construct an agent noun; Reader, Writer, Formatter, CloseNotifier etc.

Variable Declaration

In Go, a variable is a piece of storage containing a value. You can give a variable a name by using a variable declaration. Just use the var keyword, followed by the desired name and the type of values the variable will hold.

Variable declaration syntax:

var name string

  • var :- A keyword.
  • name :- A variable name that you want to access in your program.
  • string :- Any datatype that the variable will hold data for. (Go-supported datatype)

Once you declare a variable, you can assign any value of that type to it with the = sign.

var name string = "Jerry"

You can assign values to multiple variables in the same statement. Just place multiple variable names on the left side of =, and the same number of values on the right side, separated with commas (,).

Syntax for assigning multiple variables at once:

var length, width float64 = 1.2, 2.4

You can assign new values to existing variables, but they need to be values of the same type, for example: when you assign an int variable value to a string type variable. Go’s static typing ensures you don’t accidentally assign the wrong kind of value to a variable.

Short Variable Declaration

As we saw in the above section, we can declare variables and assign them values on the same line. But if you know what the initial value of a variable is going to be as soon as you declare it, it’s more typical to use a short variable declaration. Instead of explicitly declaring the type of the variable and later assigning it with =, you do both at once using :=.

Here are our previous examples with short variable declarations :

  1. name := jerry instead of var name string = "Jerry"
  2. length, width := 1.2, 2.4 instead of var length, width float64 = 1.2, 2.4

There’s no need to explicitly declare the variable’s type; the type of the value assigned to the variable becomes the type of that variable.

Because short variable declarations are so convenient and concise, they’re used more often than regular declarations. You’ll still see both forms occasionally, though, so it’s important to be familiar with both.

Thanks!!!

In this blog, we’ve delved into Go’s intriguing history, exploring its origins and essential conventions such as formatting, comments with the godoc tool, and naming guidelines. We also demystified the absence of semicolons in Go and how they are automatically inserted.

If you found this blog helpful or discovered something new, please consider sharing it with your connections who may benefit from a clearer understanding. If you’ve spotted any errors or have additional insights, please don’t hesitate to leave a comment below. Let’s engage in discussions and learn together.

Once again, a big thank you for joining me on this journey. 🥳

names

References