Click here to Skip to main content
15,886,578 members
Articles / Programming Languages / Go

Quick Overview of Go

Rate me:
Please Sign up or sign in to vote.
4.40/5 (7 votes)
14 Dec 2016CPOL12 min read 11.7K   4   4
In this article, we will quickly overview the Google's Go programming language.

GO!

Table of Contents

  1. Introduction
  2. Go Hello, World!
  3. Comments
  4. Semicolons
  5. Functions
  6. Variables
  7. Built-in Types
  8. User-Defined Types
  9. Arrays
  10. Slices
  11. Constants
  12. Pointers
  13. Statements
  14. Anonymous Functions
  15. Methods
  16. References
  17. History

Introduction

The Go is a general-purpose programming language created at Google. It’s an open source project to make programmers more productive. Go is very expressive and clean. Its concurrent programming capability helps programmers to write programs that need to get the most out of multicore and networked machines. Go is statically typed and a compiled programming language. Go compiles programs quickly into machine code. It also has the facility of garbage collection. The garbage collection makes concurrent code far easier to write. And beside all these, the Go has a very rich standard library.

Go Hello, World!

Let’s have a look at the following ‘Hello, World!’ program written in Go:

package main

import "fmt"

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

From this hello world program, we’ve got the following:

  1. A package name called main. But what is it actually?

    Well, every Go program is consists of packages. We either write a library or an executable program. An executable program belongs to the package main. This means executable programs start running in the package main. So at the beginning of a Go program, the package name is needed to be specified in the following way:

    package main

    This will tell the compiler that this program is an executable program. Not a library.

    But if we write a library, it means we are writing a new package and we give a name to the package. Suppose our new library/package name will be ‘simplelib’. If so, then at the beginning of every source file of our new library/package, the following line must be present:

    package simplelib

    This is how we tell the compiler that this source file belongs to the package ‘simplelib’.

  2. We found an import statement that is importing something called "fmt".

    An import statement is used to import external Go packages into another Go package/program. Quite similar to C’s include preprocessor directive.

    The import statement is used in the following way:

    import "package_name"

    Or (This is recommended syntax when importing more than one package):

    import (
        "package_name"
        "package_name2"
        "package_name3"
        "package_nameN"
    )

    In the hello world example, a package called fmt is imported. The package fmt implements formatted I/O with functions analogous to C's printf and scanf. The format 'verbs' are derived from C's but are simpler. So this package is necessary when interacting with console window.

  3. A user-defined function named main.

    This function is analogous to C’s entry point main. Go program’s code execution begins from this function.

  4. Inside the main function, another function named Println, is being called to print the "Hello, World!" message.

    The Println function is used to print something on the console window. This function belongs to the package fmt and that is why this package is imported at the very beginning of the hello world program.

    Go's Println very much useful. We can use this function to print values like strings or ints. Even, we can print more complex things like array. We don't need any loop to print elements of an array. The Println function automatically inserts a newline after printing all the values.

Now, we will go through some features of the Go programming language.

Comments

We programmers use comments to describe a piece of code. That makes the code easier to understand and read. There are mainly two forms of comment in Go:

  • Single line comment
  • Multiline comment

Here is an example of the single line comment:

// This is a single line comment.

And the following is an example of the multi line comment:

/* This is a multi line comment.
   This is the second line of this multi line comment.
 */

Now we can see that doing comments in Go is analogous to C++, C#, Java etc.

Semicolons

Unlike C, C++, C#, Java etc. programming language, there is no need of using semicolons in Go to indicate statement’s termination. Go’s lexer uses a simple rule to deduce a statement’s end.

Idiomatic Go programs have semicolons only in places such as for loop clauses, to separate the initializer, condition, and continuation elements. They are also necessary to separate multiple statements on a line.

Functions

In Go, function creations have the following syntax:

func function_name(input_parameter_list) (return_type_list) {
    function_stataments
}

We can see that function creation begins with a func keyword. Then we have to specify the function’s name. Function’s name should be any valid Go identifier. After that, we put all the input parameters. If a function has more than one parameter in the parameter list, they are needed to be separated via comma. And also, parameters are must be bounded by braces ( ). Then we specify the return type of the function. But if our function doesn’t require returning any value, then we can omit the return type.

For example:

func sing() {
    // I'm singing!
}

Another example of a function that does addition between two numbers and returns the result as an integer value:

func add(x int, y int) int {
    return x + y
}

Unlike C, functions can have multiple return values in Go, and it’s a built-in feature. In this case, it will require braces ( ) around the return types and all the return types are must be separated via comma operators.

For example:

func getall() (int, string) {
    return 10, "that's all!"
}

And when we call the function, multiple return values are acquired in this way (this example code uses the short variable declaration form. We will discuss about it in the ‘short variable declarations’ section):

i, s := getall()

Now variable i contains the first return value (which is 10) and the variable s contains the second return value ( which is a string and is “that's all!").

In Go, this Multiple Return Values feature is usually used to return both result and error values from a function.

The Entry Point

A global function that is named as main is recognized as the program's entry point:

func main() { 
    // function’s body
}

Note that Go’s main function does not have parameters (like argc, argv in C) to access command-line arguments. However, a Go package called os gives a solution to that problem. The Args variable of the os package provides access to raw command-line arguments. For example:

package main

import (
    "fmt"
    "os"
)

func main() {
    fmt.Println(len(os.Args), os.Args)
}

Variables

Variable declarations in Go have the following syntaxes:

  1. var identifier_list type
  2. var identifier_list = initializer_expression_list
  3. var identifier_list type = initializer_expression_list

Example:

var i int
var a, b, c int
var k = 0
var x, y int = 12, 9

We can see that variable declaration in Go begin with a var keyword. And also, it isn't always require specifying the type explicitly. We can let the compiler to deduce variable’s type from the initializer expression. This is just like we do in C++11 using an auto keyword.

Short Variable Declarations

A short variable declaration has the following syntax which doesn’t require the var keyword at the beginning of declaration and deduces variable’s type automatically:

identifier_list := initializer_expression_list

Example:

i := 80

Or:

a, b, c := 10, 20, 30

This makes coding easier and helps to write codes more quickly.

Note that the short variable declaration form can only be used inside a function. You can’t use it in the global scope.

Built-in Types

The following is the list of all the basic/built-in types available in Go:

  • bool - Consists of the two predefined constants true and false
  • string - Represents sequence of characters
  • int8 - Signed 8-bit integer (-128 to 127)
  • int16 - Signed 16-bit integer (-32768 to 32767)
  • int32 - Signed 32-bit integer (-2147483648 to 2147483647)
  • int64 - Signed 64-bit integer (-9223372036854775808 to 9223372036854775807)
  • int - Signed 32 or 64 bit integer ( depends on system )
  • uint8 - Unsigned 8-bit integer (0 to 255)
  • uint16 - Unsigned 16-bit integer (0 to 65535)
  • uint32 - Unsigned 32-bit integer (0 to 4294967295)
  • uint64 - Unsigned 64-bit integer (0 to 18446744073709551615)
  • uint - Unsigned 32 or 64 bit integer ( depends on system )
  • uintptr - Unsigned 32 or 64 bit integer ( depends on system )
  • byte ( alias for uint8 )
  • rune (alias for int32 )
  • float32 - IEEE-754 32-bit floating-point number
  • float64 - IEEE-754 64-bit floating-point number
  • complex64 - Complex number with float32 real and imaginary parts
  • complex128 - Complex number with float64 real and imaginary parts

Note: The int, uint, and uintptr types are usually 32 bits wide on 32-bit systems and 64 bits wide on 64-bit systems. When you need an integer value you should use int unless you have a specific reason to use a sized or unsigned integer type.

User-Defined Types

There are mainly two kinds of user-defined types in Go:

  1. Structure
  2. Interface

Structure

A structure allows programmers to hold several variables of same or different types together.

In Go, type and struct keywords are needed to be used in order to create a structure. The syntax of creating a structure is the following:

type identifier struct {
    structure_members
}

Example of a structure that is consists of four variables of same types:

type Rectangle struct {
    left int
    top int
    right int
    bottom int
}

Another example of a structure that is consists of three variables of different types:

type Person struct {
    name string
    age int
    income float32
}

Use of structure:

var rect Rectangle

rect.left = 20
rect.top = 10
rect.right = 50
rect.bottom = 60

fmt.Println("left: ", rect.left)
fmt.Println("top: ", rect.top)
fmt.Println("right: ", rect.right)
fmt.Println("bottom: ", rect.bottom)

Go allows to initialize a structure's members during variable declaration:

var r = Rectangle{20, 10, 50, 60}

Interface

The syntax of an interface in Go is the following:

type identifier interface {
    interface_methods
}

Example:

type Person interface {
    Name() string
    Age() int
    Flee()
    Die()
}

Another practical example of using Interfaces:

package main

import "fmt"

type Greeting interface {
    Say()
}

type EngGreeting struct {
    // Implement the Greeting interface.
    Greeting
}

type BanGreeting struct {
    // Implement the Greeting interface.
    Greeting
}

func (e * EngGreeting) Say() {
    // Implement method Say for EngGreeting struct.
    fmt.Println("Hello Forhad Reja")
}

func (e * BanGreeting) Say() {
    // Implement method Say for BanGreeting struct.
    fmt.Println("ওহে ফরহাদ রেজা")
}

// This function doesn't care whether 'g' will be a Bengali or English greeting ;)
func say(g Greeting) {
    g.Say()
}

func main() {
    // create an instance of EngGreeting.
    e := new(EngGreeting)
    say(e)

    // create an instance of BanGreeting.
    b := new(BanGreeting)
    say(b)
}

Arrays

Arrays creation syntax in Go is slightly different than C++, C# etc programming language. The square brackets are placed just before the element type:

[ array_length_expression ] element_type

The array length expression must be an integer contsant greater than zero.

Example of creating single and multidimensional array:

var ar [10]int
var mat [4][4]int
var big [10][10][10]int

Arrays can be initialized when creating:

var ar = [3]int{12, 10, 32}

Let's see an example of assigning value to a array’s single element. Note that array's index starts at 0 and the last index is one less than the array's total length:

ar[0] = 5
mat[0][0] = 12

Accessing array’s single element:

fmt.Println(ar[0], mat[0][0])

Slices

There is no built-in dynamic arrays in Go. But wait… there are slices.

Slices allow us to increase the size of an array dynamically. Slices are can be created using the following syntax in Go:

[  ] element_type

For example:

var da []int = []int{9, 8, 7}

fmt.Println(da)

Prints:

[9 8 7]

Go has built-in functions to perform operations on a slice/dynamic array. Here is an example of adding new item to the array using the built-in append function:

da = append(da, 4)
fmt.Println(da)

Now it prints:

[9 8 7 4]

Constants

Constants are fixed values that are can’t be changed during the program’s execution. Constant declarations are begins with a const keyword. The syntax is similar to the syntax of variable declaration, except the var keyword is replaced with the const keyword:

const Pi float64 = 3.14159265358979323846
const zero = 0.0
const (
	size int64 = 1024
	eof        = -1
)
const a, b, c = 3, 4, "foo"
const u, v float32 = 0, 3

Pointers

Like C, C++, Go supports pointers. We can create pointer variables that can hold another variable’s address. And through the pointer variable, we can set a value to the original variable. An ampersand & operator is used to take a variable’s address and an asterisk * operator is used for dereferencing.

To create a pointer variable with explicit type, ‘*’ symbol must be placed just before the type name.

Example of creating a pointer variable with explicit type:

var p *int

Usage:

// create a value type variable
var n = 42
// let’s get the address of the variable ‘n’
p = &n
// now, through the pointer variable ‘p’, assign 10 to the variable ‘n’
*p = 10

Now, if we print the value of the variable n, we will get exactly 10.

We can also create pointers using the short variable declaration form:

p := &n

One thing to note that Go has no pointer arithmetic. This means you can’t simply do operations like p++ or p += 1.

So the following statement:

p++

Will generate this error:

invalid operation: p++ (non-numeric type *int)

Statements

There are many kinds of statements in Go. We will discuss about few of them.

  1. If/Else Statement

    if condition_expression {
    	// if body
    } else {
    	// else body
    }

    The if/else statement works on condition. If the given condition expression evaluates to true, the “if” body’s codes are executed, otherwise, if present, the “else” body’s codes are executed.

    Example:

    if 7%2 == 0 {
        fmt.Println("7 is even")
    } else {
        fmt.Println("7 is odd")
    }

    One can use the ‘if’ without an ‘else’. For example:

    if age == 12 {
        fmt.Println("too young")
    }

    Note that you don’t need parentheses around conditions in Go that usually needs in C++, C#, Java etc programming languages. And also, there is no ternary operator in Go. You have to use a full if statement even for basic conditions.

  2. For Statement

    The for is Go’s only loop statement. There is no such while, do-while, foreach etc. loop statements in Go. Although, the for statement of Go can cover all of them.

    The following is the simplest form of the for statement and works just like a while loop statement:

    i := 0
    for i < 10 {
        fmt.Println(i)
        i = i + 1
    }

    The classic initial/condition/after for loop:

    for i := 0; i < 10; i++ {
        fmt.Println(i)
    }

    And this is another form of the for statement with range clause. This form is used to iterate over a slice or map:

    ar := []int{1, 2, 4, 8, 16, 32, 64, 128}
    
    for i, v := range ar {
       fmt.Printf(i, v)
    }

    When ranging over a slice, two values are returned for each iteration. The first is the index, and the second is a copy of the element at that index.

  3. Switch Statement

    Go’s switch statement is very much like the switch statement of C++, except each case body breaks automatically. Doesn’t need to put a break statement explicitly:

    switch age {
        case 10:
            fmt.Println("Kid")
        case 16:
            fmt.Println("Teen")
        default:
            fmt.Printf("Why are you?")
    }

    Although, one can use a fallthrough statement to fall through a case to the next case:

    switch age {
        case 8:
            fallthrough
        case 10:
            fmt.Println("Kid")
        case 16:
            fmt.Println("Teen")
        default:
            fmt.Println("Why are you?")
    }
  4. Defer statement

    A defer statement is used to call a function whose execution doesn’t happen immediately. Rather the execution is deferred to the moment the surrounding function returns. The defer statement is usually used to simplify functions that perform various clean-up actions.

    Let’s see an example of how the defer statements work:

    package main
    
    import "fmt"
    
    func main() {
        defer fmt.Println("Hoorraa!… I’m deferred!")
        defer fmt.Println("Yeah… I’m also deferred!")
    
        fmt.Printf("Stop deferring!")
        return
    }

    Prints the following:

    Stop deferring!
    Yeah… I’m also deferred!
    Hoorraa!… I’m deferred!

    Now we can see that the execution order is totally reversed. And that’s how the defer statement actually works. The last deferred function call gets executed first when the surrounding function returns.

    Another example:

    func main() {
        for i := 0; i <= 3; i++ {
            defer fmt.Print(i)
        }
    }

    Prints:

    3 2 1 0

Anonymous Functions

Go language supports anonymous functions. Anonymous functions are useful when we want to create functions without names! They are often called lambda functions or simply lambda.

Example:

package main

import "fmt"

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

Example 2:

// put a function into variable ‘greeting’
greeting := func() {
    fmt.Println("Hello, World!")
}

// let’s invoke the function
greeting()

Closures

Go’s anonymous functions can form closures. A closure is a function value that references variables from outside its body. The function may access and assign to the referenced variables; in this sense, the function is "bound" to the variables.

Example:

package main

import "fmt"

func adder() func(int) int {
	num := 0
	return func(x int) int {
		num += x
		return num
	}
}

func main() {
    pos, neg := adder(), adder()
    for i := 0; i < 10; i++ {
        fmt.Println(pos(i), neg(-i))
    }
}

Methods

Go does not have classes. However, we can define methods on struct types. A method basically is a function with a special receiver argument. The receiver argument appears in its own argument list between the func keyword and the method name.

In the following example, we will implement two methods called width and height for the Rectangle struct:

package main

import "fmt"

type Rectangle struct {
    left int
    top int
    right int
    bottom int
}

func (r *Rectangle) width() int {
	return r.right - r.left
}

func (r Rectangle) height() int {
	return r.bottom - r.top
}

func main() {
    r := Rectangle{20, 10, 50, 50}
    fmt.Println("width: ", r.width())
    fmt.Println("height: ", r.height())
}

Prints:

width: 30
height: 40

We can either use value type or pointer type for the receiver argument. Go automatically handles conversion between values and pointers for method calls. Though, you may want to use a pointer receiver type to avoid copying on method calls or to allow the method to modify the receiving structure’s data.

References

History

  • First Version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Bangladesh Bangladesh
Hi, I'm Shah Farhad Reza. I'm a desktop and web software developer.

Recently I've developed an web based ERP (Enterprise Resource Planning) Software for a manufacturing company. The software is in use and working effectively fulfilling its goal (Alhamdulillah) - [February 10, 2023]

The areas of my expertise are the followings:

- OS Kernel developing.
- Programming language's compiler design and implement.
- Expert in C, C++ and Visual Basic and have basic knowledge on C#, D, Java.
- A few times used the Microsoft's new language F#.
- SQL Database programming.
- I've basic knowledge on lowest level programming language like assembly.
- Learning Mozilla’s Rust & Google’s GO programming language for software development.
- Code optimization for performance.
- Multi-threaded programming in C/C++ and Java.
- Know various advanced computer algorithm and have used them to develop graphics and simulation programs. Also working with Linear Algebra and keen to learn Quadratic Algebra in future.
- Graphics and Game programming (Both 2D and 3D).

Currently, I'm doing research on programming language and its compiler development. I've made various kind of software and now I want to share my experiences with people.


Comments and Discussions

 
Praisecomment Pin
GowitekTechie27-May-19 23:48
GowitekTechie27-May-19 23:48 
SuggestionEnsure proper use of straight and curly quotes for strings Pin
E. Anderson14-Dec-16 6:07
E. Anderson14-Dec-16 6:07 
GeneralRe: Ensure proper use of straight and curly quotes for strings Pin
Farhad Reza14-Dec-16 6:23
Farhad Reza14-Dec-16 6:23 
GeneralRe: Ensure proper use of straight and curly quotes for strings Pin
Farhad Reza15-Dec-16 0:45
Farhad Reza15-Dec-16 0:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.