Go Tutorial

Go exercises, go assignment operators, assignment operators.

Assignment operators are used to assign values to variables.

In the example below, we use the assignment operator ( = ) to assign the value 10 to a variable called x :

The addition assignment operator ( += ) adds a value to a variable:

A list of all assignment operators:

Operator Example Same As Try it
= x = 5 x = 5
+= x += 3 x = x + 3
-= x -= 3 x = x - 3
*= x *= 3 x = x * 3
/= x /= 3 x = x / 3
%= x %= 3 x = x % 3
&= x &= 3 x = x & 3
|= x |= 3 x = x | 3
^= x ^= 3 x = x ^ 3
>>= x >>= 3 x = x >> 3
<<= x <<= 3 x = x << 3

Get Certified

COLOR PICKER

colorpicker

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail: [email protected]

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail: [email protected]

Top Tutorials

Top references, top examples, get certified.

Popular Tutorials

Popular examples, learn python interactively, go introduction.

  • Golang Getting Started
  • Go Variables
  • Go Data Types
  • Go Print Statement
  • Go Take Input
  • Go Comments

Go Operators

  • Go Type Casting

Go Flow Control

  • Go Boolean Expression
  • Go if...else
  • Go for Loop
  • Go while Loop
  • Go break and continue

Go Data Structures

  • Go Functions
  • Go Variable Scope
  • Go Recursion
  • Go Anonymous Function
  • Go Packages

Go Pointers & Interface

Go Pointers

  • Go Pointers and Functions
  • Go Pointers to Struct
  • Go Interface
  • Go Empty Interface
  • Go Type Assertions

Go Additional Topics

Go defer, panic, and recover

Go Tutorials

Go Booleans (Relational and Logical Operators)

  • Go Pointers to Structs

In Computer Programming, an operator is a symbol that performs operations on a value or a variable.

For example, + is an operator that is used to add two numbers.

Go programming provides wide range of operators that are categorized into following major categories:

  • Arithmetic operators
  • Assignment operator
  • Relational operators
  • Logical operators
  • Arithmetic Operator

We use arithmetic operators to perform arithmetic operations like addition, subtraction, multiplication, and division.

Here's a list of various arithmetic operators available in Go.

Operators Example
(Addition)
(Subtraction)
(Multiplication)
(Division)
(Modulo Division)

Example 1: Addition, Subtraction and Multiplication Operators

Example 2: golang division operator.

In the above example, we have used the / operator to divide two numbers: 11 and 4 . Here, we get the output 2 .

However, in normal calculation, 11 / 4 gives 2.75 . This is because when we use the / operator with integer values, we get the quotients instead of the actual result.

The division operator with integer values returns the quotient.

If we want the actual result we should always use the / operator with floating point numbers. For example,

Here, we get the actual result after division.

Example 3: Modulus Operator in Go

In the above example, we have used the modulo operator with numbers: 11 and 4 . Here, we get the result 3 .

This is because in programming, the modulo operator always returns the remainder after division.

The modulo operator in golang returns the remainder after division.

Note: The modulo operator is always used with integer values.

  • Increment and Decrement Operator in Go

In Golang, we use ++ (increment) and -- (decrement) operators to increase and decrease the value of a variable by 1 respectively. For example,

In the above example,

  • num++ - increases the value of num by 1 , from 5 to 6
  • num-- - decreases the value of num by 1 , from 5 to 4

Note: We have used ++ and -- as prefixes (before variable). However, we can also use them as postfixes ( num++ and num-- ).

There is a slight difference between using increment and decrement operators as prefixes and postfixes. To learn the difference, visit Increment and Decrement Operator as Prefix and Postfix .

  • Go Assignment Operators

We use the assignment operator to assign values to a variable. For example,

Here, the = operator assigns the value on right ( 34 ) to the variable on left ( number ).

Example: Assignment Operator in Go

In the above example, we have used the assignment operator to assign the value of the num variable to the result variable.

  • Compound Assignment Operators

In Go, we can also use an assignment operator together with an arithmetic operator. For example,

Here, += is additional assignment operator. It first adds 6 to the value of number ( 2 ) and assigns the final result ( 8 ) to number .

Here's a list of various compound assignment operators available in Golang.

Operator Example Same as
(addition assignment)
(subtraction assignment)
(multiplication assignment)
(division assignment)
(modulo assignment)
  • Relational Operators in Golang

We use the relational operators to compare two values or variables. For example,

Here, == is a relational operator that checks if 5 is equal to 6 .

A relational operator returns

  • true if the comparison between two values is correct
  • false if the comparison is wrong

Here's a list of various relational operators available in Go:

Operator Example Descriptions
(equal to) returns if and are equal
(not equal to) returns if and are not equal
(greater than) returns if is greater than
(less than) returns if is less than
(greater than or equal to) returns if is either greater than or equal to
(less than or equal to) returns is is either less than or equal to

To learn more, visit Go relational operators .

  • Logical Operators in Go

We use the logical operators to perform logical operations. A logical operator returns either true or false depending upon the conditions.

Operator Description Example
(Logical AND) returns if both expressions and are
(Logical OR) returns if any one of the expressions is .
(Logical NOT) returns if is and returns if is .

To learn more, visit Go logical operators .

More on Go Operators

The right shift operator shifts all bits towards the right by a certain number of specified bits.

Suppose we want to right shift a number 212 by some bits then,

For example,

The left shift operator shifts all bits towards the left by a certain number of specified bits. The bit positions that have been vacated by the left shift operator are filled with 0 .

Suppose we want to left shift a number 212 by some bits then,

In Go, & is the address operator that is used for pointers. It holds the memory address of a variable. For example,

Here, we have used the * operator to declare the pointer variable. To learn more, visit Go Pointers .

In Go, * is the dereferencing operator used to declare a pointer variable. A pointer variable stores the memory address. For example,

In Go, we use the concept called operator precedence which determines which operator is executed first if multiple operators are used together. For example,

Here, the / operator is executed first followed by the * operator. The + and - operators are respectively executed at last.

This is because operators with the higher precedence are executed first and operators with lower precedence are executed last.

Table of Contents

  • Introduction
  • Example: Addition, Subtraction and Multiplication
  • Golang Division Operator

Sorry about that.

Our premium learning platform, created with over a decade of experience and thousands of feedbacks .

Learn and improve your coding skills like never before.

  • Interactive Courses
  • Certificates
  • 2000+ Challenges

Related Tutorials

Programming

Go Design Patterns

This post will briefly describe the differences between the assignments and short variable declarations in Go. It assumes that you have completed A Tour of Go and have consulted relevant sections of Effective Go and the target audience is primarily newcomers to the Go programming language.

The assignment operator ( = ) is used to perform assignments (i.e. to assign or reassign values to already declared variables).

The short declaration operator ( := ), on the other hand, is used to perform short variable declarations ), which are shorthand for regular variable declarations but without a specified type.

Here are four different ways to create a variable with static type int and value 10 , each of which are equivalent:

Unlike regular variable declarations, a short variable declaration may redeclare variables in multi-value assignments, assuming at least one variable is new and the redeclared variable is assigned a value of the same type. You’ll see this property used frequently when dealing with errors, as it avoids the need to declare differently named variables such as err1 , err2 , etc. in the same block of code. For example, consider the CopyFunc function below, which opens two files and copies the contents of one file to the other:

In general, short variable declarations should be preferred because they are more concise than regular variable declarations/assignments. Note, however, that short variable declarations can only be used inside of functions/methods (declaring global variables at the package level can only be done using a regular variable declaration: var name type = value ).

Recommended Readings:

  • The Assignments and Short variable declarations sections in the official Go Programming Language Specification.
  • The Redeclaration and reassignment section in Effective Go.
  • Handling errors and Go from the Go Blog.
  • The Blank identifier in multiple assignment section in Effective Go.

+1 this blog!

Go Design Patterns is a website for developers who wish to better understand the Go programming language. The tutorials here emphasize proper code design and project maintainability.

Find a typo?

Submit a pull request! The code powering this site is open-source and available on GitHub . Corrections are appreciated and encouraged! Click here for instructions.

© 2014-2018 Alex Lockwood | Android Design Patterns | Go Design Patterns | 2048++

Golang Libraries, Apps, Golang Jobs and Go Tutorials

Golang News, Tutorials, Go Libraries and Golang Jobs

  • Golang Jobs / Go Developer Jobs
  • Go/JS Full Stack Development

Golang Variables Declaration, Assignment and Scope Tutorial

This tutorial will explain how to work with variables in Golang, and some conventions used for idiomatic Go code. Variables in Golang, just like in other languages, are used to store and represent data. Every variable in Go has a type and a value.

If you just want to read some example code, you can view it  on Github .

Golang Variable Declaration

Lets look at the declaration of an integer type:

This declares a variable named  i  of type  int  with a value of  5 . The Go compiler is pretty smart, so you can sometimes omit some declarations. For example:

The compiler infers that  5  is of type  int , and so assigns that type to  i .

Default Values with Golang Variables

We can also declare the type without declaring the value. If we do this, the variable is assigned a default value, which depends on the type:

Now the value of  i  is initialized to the default value, which is  0  for the  int  type.

Different types have different default values:

typeDefault ValueNotes
Initialized to 0
Initialized to 0
Empty string
Pointers to any type default to nil
structs initialize to the default values of their attributes
Function variables are initialized as nil

Shorthand Declaration

Golang Libraries, Apps, Golang Jobs and Go Tutorials 2024 . Powered by WordPress

Go Tutorial

  • Go Tutorial
  • Go - Overview
  • Go - Environment Setup
  • Go - Program Structure
  • Go - Basic Syntax
  • Go - Data Types
  • Go - Variables
  • Go - Constants
  • Go - Operators
  • Go - Decision Making
  • Go - Functions
  • Go - Scope Rules
  • Go - Strings
  • Go - Arrays
  • Go - Pointers
  • Go - Structures
  • Go - Recursion
  • Go - Type Casting
  • Go - Interfaces
  • Go - Error Handling
  • Go Useful Resources
  • Go - Questions and Answers
  • Go - Quick Guide
  • Go - Useful Resources
  • Go - Discussion
  • Selected Reading
  • UPSC IAS Exams Notes
  • Developer's Best Practices
  • Questions and Answers
  • Effective Resume Writing
  • HR Interview Questions
  • Computer Glossary

Go - Assignment Operators

The following table lists all the assignment operators supported by Go language −

Operator Description Example
= Simple assignment operator, Assigns values from right side operands to left side operand C = A + B will assign value of A + B into C
+= Add AND assignment operator, It adds right operand to the left operand and assign the result to left operand C += A is equivalent to C = C + A
-= Subtract AND assignment operator, It subtracts right operand from the left operand and assign the result to left operand C -= A is equivalent to C = C - A
*= Multiply AND assignment operator, It multiplies right operand with the left operand and assign the result to left operand C *= A is equivalent to C = C * A
/= Divide AND assignment operator, It divides left operand with the right operand and assign the result to left operand C /= A is equivalent to C = C / A
%= Modulus AND assignment operator, It takes modulus using two operands and assign the result to left operand C %= A is equivalent to C = C % A
<<= Left shift AND assignment operator C <<= 2 is same as C = C << 2
>>= Right shift AND assignment operator C >>= 2 is same as C = C >> 2
&= Bitwise AND assignment operator C &= 2 is same as C = C & 2
^= bitwise exclusive OR and assignment operator C ^= 2 is same as C = C ^ 2
|= bitwise inclusive OR and assignment operator C |= 2 is same as C = C | 2

Try the following example to understand all the assignment operators available in Go programming language −

When you compile and execute the above program it produces the following result −

The Golang Handbook – A Beginner's Guide to Learning Go

Lane Wagner

The Go programming language has been exploding in popularity. Tons of companies are using Go to build scalable, modern, backend infrastructure.

If you're looking to learn a new programming language, Go is a great choice. It's fast, lightweight, has an amazing open source community, and is actually quite easy to get started with.

This a completely free text-based handbook. If you want to get started, just scroll down and start reading! That said, there are two other options for following along.

  • Try the interactive version of this Golang course on Boot.dev , complete with coding challenges and projects
  • Watch the video walkthrough of this course on FreeCodeCamp's YouTube channel (embedded below)

Table of Contents

  • Why Learn Go?
  • How to Compile Go Code
  • Variables in Go
  • Functions in Go
  • Structs in Go
  • Interfaces in Go
  • Errors in Go
  • Loops in Go
  • Arrays and Slices in Go
  • Advanced Functions in Go
  • Pointers in Go
  • Local Development in Go

Channels in Go

  • Mutexes in Go
  • Generics in Go

Chapter 1 – Why Learn Go?

Go is fast, simple, and productive. Go is one of the fastest programming languages, beating JavaScript, Python, and Ruby handily in most benchmarks.

But, Go code doesn't run quite as fast as its compiled Rust and C counterparts. That said, it compiles much faster than they do, which makes the developer experience super productive. Unfortunately, there are no swordfights on Go teams...

Image

Go has been growing like crazy in the backend development industry, so if you're interested in getting a job as a backend dev , Go can be a great choice of technology to add to your tool belt.

How to Download and Install the Go Toolchain

I typically recommend one of two ways:

  • Official Download
  • Webi Downloader

Make sure to use at least version 1.20 . You can verify this after installation by typing:

A note on the structure of a Go program

We'll go over this all later in more detail, but to sate your curiosity for now, here are a few tidbits about the code:

  • package main lets the Go compiler know that we want this code to compile and run as a standalone program, as opposed to being a library that's imported by other programs.
  • import fmt imports the fmt (formatting) package. The formatting package exists in Go's standard library and let's us do things like print text to the console.
  • func main() defines the main function. main is the name of the function that acts as the entry point for a Go program.

Save the code above in a file called main.go , run go build , and then run the resulting executable.

You can also use Bootdev's Go playground to try out all the snippets in this course right from your browser.

Chapter 2 – How to Compile Go Code

What does it mean to be compiled.

Computers need machine code – they don't understand English or even Go. We need to convert our high-level (Go) code into machine language, which is really just a set of instructions that some specific hardware can understand. In your case, your CPU.

The Go compiler's job is to take Go code and produce machine code. On Windows, that would be a .exe file. On Mac or Linux, it would be any executable file.

Computers don't know how to do anything unless we as programmers tell them what to do. Unfortunately, computers don't understand human language. In fact, they don't even understand uncompiled computer programs.

For example, the code:

means nothing to a computer.

Computers need machine code

A computer's CPU only understands its own instruction set , which we call "machine code". Instructions are basic math operations like addition, subtraction, multiplication, and the ability to save data temporarily.

For example, an ARM processor uses the ADD instruction when supplied with the number 0100 in binary.

Go, C, Rust, and so on

Go, C, and Rust are all languages where the code is first converted to machine code by the compiler before it's executed.

Image

Compiled vs Interpreted

Compiled programs can be run without access to the original source code, and without access to a compiler.

For example, when your browser executes the code you write in this course, it doesn't use the original code, just the compiled result. Note how this is different than interpreted languages like Python and JavaScript.

With Python and JavaScript, the code is interpreted at runtime by a separate program known as the "interpreter". Distributing code for users to run can be a pain because they need to have an interpreter installed, and they need access to the original source code.

Examples of compiled languages

Examples of interpreted languages.

Image

Go is Strongly Typed

Go enforces strong and static typing, meaning variables can only have a single type. A string variable like "hello world" can not be changed to an int , such as the number 3 .

One of the biggest benefits of strong typing is that errors can be caught at "compile time". In other words, bugs are more easily caught ahead of time because they are detected when the code is compiled before it even runs.

Contrast this with most interpreted languages, where the variable types are dynamic. Dynamic typing can lead to subtle bugs that are hard to detect. With interpreted languages, the code must be run (sometimes in production if you are unlucky 😨) to catch syntax and type errors.

As an example, the following code will fail to compile because strings and ints can't be added together:

Go programs are lightweight

Go programs are fairly lightweight. Each program includes a small amount of "extra" code that's included in the executable binary. This extra code is called the Go Runtime . One of the purposes of the Go runtime is to cleanup unused memory at runtime.

In other words, the Go compiler includes a small amount of extra logic in every Go program to make it easier for developers to write code that's memory efficient.

As a general rule, Java programs use more memory than comparable Go programs because Go doesn't use an entire virtual machine to run its programs, just a small runtime. The Go runtime is small enough that it is included directly in each Go program's compiled machine code.

As another general rule, Rust and C++ programs use slightly less memory than Go programs because more control is given to the developer to optimize memory usage of the program. The Go runtime just handles it for us automatically.

Image

In the chart above, Dexter Darwich compares the memory usage of three very simple programs written in Java, Go, and Rust. As you can see, Go and Rust use very little memory when compared to Java.

Chapter 3 – Variables in Go

Go's basic variable types are:

We talked about string s and int s previously, and those two types should be fairly self-explanatory.

A bool is a boolean variable, meaning it has a value of true or false . The floating point types ( float32 and float64 ) are used for numbers that are not integers – that is, they have digits to the right of the decimal place, such as 3.14159 . The float32 type uses 32 bits of precision, while the float64 type uses 64 bits to be able to more precisely store more digits.

Don't worry too much about the intricacies of the other types for now. We will cover some of them in more detail as we progress.

How to declare a variable

Variables are declared using the var keyword. For example, to declare a variable called number of type int , you would write:

To declare a variable called pi to be of type float64 with a value of 3.14159 , you would write:

The value of an initialized variable with no assignment will be its zero value .

Short Variable Declaration

Inside a function (even the main function), the := short assignment statement can be used in place of a var declaration. The := operator infers the type of the new variable based on the value.

Is the same as:

Outside of a function (in the global/package scope ), every statement begins with a keyword ( var , func , and so on) and so the := construct is not available.

Type Inference

To declare a variable without specifying an explicit type (either by using the := syntax or var = expression syntax), the variable's type is inferred from the value on the right hand side.

When the right hand side of the declaration is typed, the new variable is of that same type:

However, when the right hand side is a literal value (an untyped numeric constant like 42 or 3.14 ), the new variable will be an int , float64 , or complex128 depending on its precision:

Same Line Declarations

We can declare multiple variables on the same line:

Ints, uints , floats , and complex numbers all have type sizes.

The size (8, 16, 32, 64, 128, and so on) indicates how many bits in memory will be used to store the variable. The default int and uint types are just aliases that refer to their respective 32 or 64 bit sizes depending on the environment of the user.

The standard sizes that should be used unless you have a specific need are:

Some types can be converted the following way:

Casting a float to an integer in this way truncates the floating point portion.

Which Type Should I Use?

With so many types for what is essentially just a number, developers coming from languages that only have one kind of Number type (like JavaScript) may find the choices daunting.

A problem arises when we have a uint16 , and the function we are trying to pass it into takes an int . We're forced to write code riddled with type casts like int(myUint16) .

This style of development can be slow and annoying to read. When Go developers stray from the “default” type for any given type family, the code can get messy quickly.

Unless you have a good reason to, stick to the following types:

Constants are declared like variables but use the const keyword. Constants can't use the := short declaration syntax.

Constants can be character, string, boolean, or numeric values. They can not be more complex types like slices, maps and structs, which are types I will explain later.

As the name implies, the value of a constant can't be changed after it has been declared.

Constants must be known at compile time . More often than not they will be declared with a static value:

However, constants can be computed so long as the computation can happen at compile time. For example, this is valid:

That said, you can't declare a constant that can only be computed at run-time.

How to Format Strings in Go

Go follows the printf tradition from the C language. In my opinion, string formatting/interpolation in Go is currently less elegant than JavaScript and Python.

  • fmt.Printf – Prints a formatted string to standard out
  • fmt.Sprintf() – Returns the formatted string

These formatting verbs work with both fmt.Printf and fmt.Sprintf .

%v - Interpolate the default representation

The %v variant prints the Go syntax representation of a value. You can usually use this if you're unsure what else to use. That said, it's better to use the type-specific variant if you can.

%s - Interpolate a string

%d - interpolate an integer in decimal form, %f - interpolate a decimal.

If you're interested in all the formatting options, feel free to take a look at the fmt package's docs here .

Conditionals

if statements in Go don't use parentheses around the condition:

else if and else are supported as you would expect:

The initial statement of an if block

An if conditional can have an "initial" statement. The variable(s) created in the initial statement are only defined within the scope of the if body.

This is just some syntactic sugar that Go offers to shorten up code in some cases. For example, instead of writing:

Not only is this code a bit shorter, but it also removes length from the parent scope. This is convenient because we don't need it there – we only need access to it while checking a condition.

Chapter 4 – Functions in Go

Functions in Go can take zero or more arguments.

To make Go code easier to read, the variable type comes after the variable name.

For example, the following function:

Accepts two integer parameters and returns another integer.

Here, func sub(x int, y int) int is known as the "function signature".

Multiple Parameters

When multiple arguments are of the same type, the type only needs to be declared after the last one, assuming they are in order.

For example:

If they are not in order they need to be defined separately.

Function Declaration Syntax

Developers often wonder why the declaration syntax in Go is different from the tradition established in the C family of languages.

C-Style syntax

The C language describes types with an expression including the name to be declared, and states what type that expression will have.

The code above declares y as an int . In general, the type goes on the left and the expression on the right.

Interestingly, the creators of the Go language agreed that the C-style of declaring types in signatures gets confusing really fast – take a look at this nightmare.

Go-style syntax

Go's declarations are clear, you just read them left to right, just like you would in English.

It's nice for more complex signatures, as it makes them easier to read.

How to Pass Variables by Value

Variables in Go are passed by value (except for a few data types we haven't covered yet). "Pass by value" means that when a variable is passed into a function, that function receives a copy of the variable. The function is unable to mutate the caller's original data.

How to Ignore Return Values

A function can return a value that the caller doesn't care about. We can explicitly ignore variables by using an underscore: _

Even though getPoint() returns two values, we can capture the first one and ignore the second.

Why would you ignore a return value?

There could be many reasons. For example, maybe a function called getCircle returns the center point and the radius, but you really only need the radius for your calculation. In that case, you would ignore the center point variable.

This is crucial to understand because the Go compiler will throw an error if you have unused variable declarations in your code, so you need to ignore anything you don't intend to use.

Named Return Values

Return values may be given names, and if they are, then they are treated the same as if they were new variables defined at the top of the function.

Named return values are best thought of as a way to document the purpose of the returned values.

According to the tour of go :

"A return statement without arguments returns the named return values. This is known as a "naked" return. Naked return statements should be used only in short functions. They can harm readability in longer functions."

In the first example, x and y are the return values. At the end of the function, we could simply write return to return the values of those two variables, rather that writing return x,y .

Explicit Returns

Even though a function has named return values, we can still explicitly return values if we want to.

Using this explicit pattern we can even overwrite the return values:

Otherwise, if we want to return the values defined in the function signature we can just use a naked return (blank return):

The Benefits of Named Returns

Good for documentation (understanding).

Named return parameters are great for documenting a function. We know what the function is returning directly from its signature, no need for a comment.

Named return parameters are particularly important in longer functions with many return values.

Which is easier to understand than:

We know the meaning of each return value just by looking at the function signature: func calculator(a, b int) (mul, div int, err error)

Less Code (Sometimes)

If there are multiple return statements in a function, you don’t need to write all the return values each time, though you probably should.

When you choose to omit return values, it's called a naked return. Naked returns should only be used in short and simple functions.

Early Returns

Go supports the ability to return early from a function. This is a powerful feature that can clean up code, especially when used as guard clauses .

Guard Clauses leverage the ability to return early from a function (or continue through a loop) to make nested conditionals one-dimensional. Instead of using if/else chains, we just return early from the function at the end of each conditional block.

Error handling in Go naturally encourages developers to make use of guard clauses. When I started writing more JavaScript, I was disappointed to see how many nested conditionals existed in the code I was working on.

Let’s take a look at an exaggerated example of nested conditional logic:

This could be written with guard clauses instead:

The example above is much easier to read and understand. When writing code, it’s important to try to reduce the cognitive load on the reader by reducing the number of entities they need to think about at any given time.

In the first example, if the developer is trying to figure out when 270 is returned, they need to think about each branch in the logic tree and try to remember which cases matter and which cases don’t.

With the one-dimensional structure offered by guard clauses, it’s as simple as stepping through each case in order.

Chapter 5 – Structs in Go

We use structs in Go to represent structured data. It's often convenient to group different types of variables together. For example, if we want to represent a car we could do the following:

This creates a new struct type called car . All cars have a Make , Model , Height and Width .

In Go, you will often use a struct to represent information that you would have used a dictionary for in Python, or an object literal in JavaScript.

Nested Structs in Go

Structs can be nested to represent more complex entities:

The fields of a struct can be accessed using the dot . operator.

Anonymous Structs

An anonymous struct is just like a regular struct, but it is defined without a name and therefore cannot be referenced elsewhere in the code.

To create an anonymous struct, just instantiate the instance immediately using a second pair of brackets after declaring the type:

You can even nest anonymous structs as fields within other structs:

When should you use an anonymous struct?

In general, prefer named structs . Named structs make it easier to read and understand your code, and they have the nice side-effect of being reusable. I sometimes use anonymous structs when I know I won't ever need to use a struct again. For example, sometimes I'll use one to create the shape of some JSON data in HTTP handlers.

If a struct is only meant to be used once, then it makes sense to declare it in such a way that developers down the road won’t be tempted to accidentally use it again.

You can read more about anonymous structs here if you're curious.

Embedded Structs

Go is not an object-oriented language. But embedded structs provide a kind of data-only inheritance that can be useful at times.

Keep in mind, Go doesn't support classes or inheritance in the complete sense. Embedded structs are just a way to elevate and share fields between struct definitions.

Embedded vs nested

  • An embedded struct's fields are accessed at the top level, unlike nested structs.
  • Promoted fields can be accessed like normal fields except that they can't be used in composite literals

Struct Methods

While Go is not object-oriented, it does support methods that can be defined on structs. Methods are just functions that have a receiver. A receiver is a special parameter that syntactically goes before the name of the function.

A receiver is just a special kind of function parameter. Receivers are important because they will, as you'll learn in the exercises to come, allow us to define interfaces that our structs (and other types) can implement.

Chapter 6 – Interfaces in Go

Interfaces are collections of method signatures. A type "implements" an interface if it has all of the methods of the given interface defined on it.

In the following example, a "shape" must be able to return its area and perimeter. Both rect and circle fulfill the interface.

When a type implements an interface, it can then be used as the interface type.

Interfaces are implemented implicitly .

A type never declares that it implements a given interface. If an interface exists and a type has the proper methods defined, then the type automatically fulfills that interface.

Multiple Interfaces

A type can implement any number of interfaces in Go. For example, the empty interface, interface{} , is always implemented by every type because it has no requirements.

Naming interface args

Consider the following interface:

Based on the code alone, can you deduce what kinds of strings you should pass into the Copy function?

We know the function signature expects 2 string types, but what are they? Filenames? URLs? Raw string data? For that matter, what the heck is that int that's being returned?

Let's add some named arguments and return data to make it clearer.

Much better. We can see what the expectations are now. The first argument is the sourceFile , the second argument is the destinationFile , and bytesCopied , an integer, is returned.

Type Assertions in Go

When working with interfaces in Go, every once-in-awhile you'll need access to the underlying type of an interface value. You can cast an interface to its underlying type using a type assertion .

Type Switches in Go

A type switch makes it easy to do several type assertions in a series.

A type switch is similar to a regular switch statement, but the cases specify types instead of values .

fmt.Printf("%T\n", v) prints the type of a variable.

Clean Interfaces

Writing clean interfaces is hard . Frankly, anytime you’re dealing with abstractions in code, the simple can become complex very quickly if you’re not careful. Let’s go over some rules of thumb for keeping interfaces clean .

1. Keep Interfaces Small

If there is only one piece of advice that you take away from this article, make it this: keep interfaces small! Interfaces are meant to define the minimal behavior necessary to accurately represent an idea or concept.

Here is an example from the standard HTTP package of a larger interface that’s a good example of defining minimal behavior:

Any type that satisfies the interface’s behaviors can be considered by the HTTP package as a File . This is convenient because the HTTP package doesn’t need to know if it’s dealing with a file on disk, a network buffer, or a simple []byte .

2. Interfaces Should Have No Knowledge of Satisfying Types

An interface should define what is necessary for other types to classify as a member of that interface. They shouldn’t be aware of any types that happen to satisfy the interface at design time.

For example, let’s assume we are building an interface to describe the components necessary to define a car.

Color() and Speed() make perfect sense, they are methods confined to the scope of a car. IsFiretruck() is an anti-pattern. We are forcing all cars to declare whether or not they are firetrucks. In order for this pattern to make any amount of sense, we would need a whole list of possible subtypes. IsPickup() , IsSedan() , IsTank() … where does it end??

Instead, the developer should have relied on the native functionality of type assertion to derive the underlying type when given an instance of the car interface. Or, if a sub-interface is needed, it can be defined as:

Which inherits the required methods from car and adds one additional required method to make the car a firetruck .

3. Interfaces Are Not Classes

  • Interfaces are not classes, they are slimmer.
  • Interfaces don’t have constructors or deconstructors that require that data is created or destroyed.
  • Interfaces aren’t hierarchical by nature, though there is syntactic sugar to create interfaces that happen to be supersets of other interfaces.
  • Interfaces define function signatures, but not underlying behavior. Making an interface often won’t DRY up your code in regards to struct methods. For example, if five types satisfy the fmt.Stringer interface, they all need their own version of the String() function.

Chapter 7 – Errors in Go

Go programs express errors with error values. An Error is any type that implements the simple built-in error interface :

When something can go wrong in a function, that function should return an error as its last return value. Any code that calls a function that can return an error should handle errors by testing whether the error is nil .

A nil error denotes success. A non-nil error denotes failure.

The Error Interface

Because errors are just interfaces, you can build your own custom types that implement the error interface. Here's an example of a userError struct that implements the error interface:

It can then be used as an error:

Go programs express errors with error values. Error-values are any type that implements the simple built-in error interface .

Keep in mind that the way Go handles errors is fairly unique. Most languages treat errors as something special and different. For example, Python raises exception types and JavaScript throws and catches errors.

In Go, an error is just another value that we handle like any other value – however, we want! There aren't any special keywords for dealing with them.

The errors Package

The Go standard library provides an "errors" package that makes it easy to deal with errors.

Read the godoc for the errors.New() function, but here's a simple example:

Chapter 8 – Loops in Go

The basic loop in Go is written in standard C-like syntax:

INITIAL is run once at the beginning of the loop and can create variables within the scope of the loop.

CONDITION is checked before each iteration. If the condition doesn't pass then the loop breaks.

AFTER is run after each iteration.

How to Omit Conditions

Loops in Go can omit sections of a for loop. For example, the CONDITION (middle part) can be omitted which causes the loop to run forever.

No while loops in Go

Most programming languages have a concept of a while loop. Because Go allows for the omission of sections of a for loop, a while loop is just a for loop that only has a CONDITION.

Which prints:

Continue through a loop

The continue keyword stops the current iteration of a loop and continues to the next iteration. continue is a powerful way to use the "guard clause" pattern within loops.

Break out of a loop

The break keyword stops the current iteration of a loop and exits the loop.

Chapter 9 – Arrays and Slices in Go

Arrays are fixed-size groups of variables of the same type.

The type [n]T is an array of n values of type T .

To declare an array of 10 integers:

or to declare an initialized literal:

99 times out of 100 you will use a slice instead of an array when working with ordered lists.

Arrays are fixed in size. Once you make an array like [10]int you can't add an 11th element.

A slice is a dynamically-sized , flexible view of the elements of an array.

Slices always have an underlying array, though it isn't always specified explicitly. To explicitly create a slice on top of an array we can do:

The syntax is:

Where lowIndex is inclusive and highIndex is exclusive

Either lowIndex or highIndex or both can be omitted to use the entire array on that side.

How to Create New Slices in Go

Most of the time we don't need to think about the underlying array of a slice. We can create a new slice using the make function:

Slices created with make will be filled with the zero value of the type.

If we want to create a slice with a specific set of values, we can use a slice literal:

Note that the array brackets do not have a 3 in them. If they did, you'd have an array instead of a slice.

The length of a slice is simply the number of elements it contains. It is accessed using the built-in len() function:

The capacity of a slice is the number of elements in the underlying array, counting from the first element in the slice. It is accessed using the built-in cap() function:

Generally speaking, unless you're hyper-optimizing the memory usage of your program, you don't need to worry about the capacity of a slice because it will automatically grow as needed.

Variadic Functions

Many functions, especially those in the standard library, can take an arbitrary number of final arguments. This is accomplished by using the "..." syntax in the function signature.

A variadic function receives the variadic arguments as a slice.

The familiar fmt.Println() and fmt.Sprintf() are variadic! fmt.Println() prints each element with space delimiters and a newline at the end.

Spread operator

The spread operator allows us to pass a slice into a variadic function. The spread operator consists of three dots following the slice in the function call.

How to Append to a Slice

The built-in append function is used to dynamically add elements to a slice:

If the underlying array is not large enough, append() will create a new underlying array and point the slice to it.

Notice that append() is variadic. The following are all valid:

How to Range Over a Slice in Go

Go provides syntactic sugar to iterate easily over elements of a slice:

Chapter 10 – Maps in Go

Maps are similar to JavaScript objects, Python dictionaries, and Ruby hashes. Maps are a data structure that provides key->value mapping.

The zero value of a map is nil .

We can create a map by using a literal or by using the make() function:

The len() function works on a map – it returns the total number of key/value pairs.

Map Mutations

Insert an element, get an element, delete an element, check if a key exists.

If key is in m , then ok is true . If not, ok is false .

If key is not in the map, then elem is the zero value for the map's element type.

Types of Valid Map Keys

Any type can be used as the value in a map, but keys are more restrictive.

You can read more in the following section of the official Go blog .

As mentioned earlier, map keys may be of any type that is comparable . The language spec defines this precisely, but in short, comparable types are boolean, numeric, string, pointer, channel, and interface types, and structs or arrays that contain only those types.

Notably absent from the list are slices, maps, and functions. These types cannot be compared using ==, and may not be used as map keys.

It's obvious that strings, ints, and other basic types should be available as map keys, but perhaps unexpected are struct keys. Struct can be used to key data by multiple dimensions.

For example, this map of maps could be used to tally web page hits by country:

This is map of string to (map of string to int). Each key of the outer map is the path to a web page with its own inner map. Each inner map key is a two-letter country code. This expression retrieves the number of times an Australian has loaded the documentation page:

Unfortunately, this approach becomes unwieldy when adding data, as for any given outer key you must check if the inner map exists, and create it if needed:

On the other hand, a design that uses a single map with a struct key does away with all that complexity:

When a Vietnamese person visits the home page, incrementing (and possibly creating) the appropriate counter is a one-liner:

And it’s similarly straightforward to see how many Swiss people have read the spec:

Nested Maps

Maps can contain maps, creating a nested structure. For example:

Chapter 11 – Advanced Functions in Go

First-class and higher-order functions.

A programming language is said to have "first-class functions" when functions in that language are treated like any other variable.

For example, in such a language, a function can be passed as an argument to other functions, can be returned by another function, and can be assigned as a value to a variable.

A function that returns a function or accepts a function as input is called a Higher-Order Function.

Go supports first-class and higher-order functions. Another way to think of this is that a function is just another type – just like int s and string s and bool s.

For example, to accept a function as a parameter:

Function Currying in Go

Function currying is the practice of writing a function that takes a function (or functions) as input, and returns a new function.

In the example above, the selfMath function takes in a function as its parameter, and returns a function that itself returns the value of running that input function on its parameter.

Defer keyword

The defer keyword is a fairly unique feature of Go. It allows a function to be executed automatically just before its enclosing function returns.

The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.

Deferred functions are typically used to close database connections, file handlers and the like.

In the above example, the src.Close() function is not called until after the CopyFile function was called but immediately before the CopyFile function returns.

Defer is a great way to make sure that something happens at the end of a function, even if there are multiple return statements.

A closure is a function that references variables from outside its own function body. The function may access and assign to the referenced variables.

In this example, the concatter() function returns a function that has reference to an enclosed doc value. Each successive call to harryPotterAggregator mutates that same doc variable.

Anonymous Functions

Anonymous functions are true to form in that they have no name . We've been using them throughout this chapter, but we haven't really talked about them yet.

Anonymous functions are useful when defining a function that will only be used once or to create a quick closure .

Chapter 12 – Pointers in Go

As we have learned, a variable is a named location in memory that stores a value. We can manipulate the value of a variable by assigning a new value to it or by performing operations on it. When we assign a value to a variable, we are storing that value in a specific location in memory.

A pointer is a variable

A pointer is a variable that stores the memory address of another variable. This means that a pointer "points to" the location of where the data is stored NOT the actual data itself.

The * syntax defines a pointer:

The & operator generates a pointer to its operand.

Why are pointers useful?

Pointers allow us to manipulate data in memory directly, without making copies or duplicating data. This can make programs more efficient and allow us to do things that would be difficult or impossible without them.

Pointer Syntax

A pointer's zero value is nil

The & operator generates a pointer to its operand:

The * dereferences a pointer to gain access to the value:

Unlike C, Go has no pointer arithmetic

Just because you can doesn't mean you should

We're doing this exercise to understand that pointers can be used in this way. That said, pointers can be very dangerous. It's generally a better idea to have your functions accept non-pointers and return new values rather than mutating pointer inputs.

Nil Pointers

Again, pointers can be very dangerous.

If a pointer points to nothing (the zero value of the pointer type) then dereferencing it will cause a runtime error (a panic ) that crashes the program.

Generally speaking, whenever you're dealing with pointers you should check if it's nil before trying to dereference it.

Pointer Method Receivers

A receiver type on a method can be a pointer.

Methods with pointer receivers can modify the value to which the receiver points. Since methods often need to modify their receiver, pointer receivers are more common than value receivers.

Pointer receiver

Non-pointer receiver.

Methods with pointer receivers don't require that a pointer is used to call the method. The pointer will automatically be derived from the value.

Chapter 13 – Local Development Environment in Go

Make sure you have Go installed on your local machine.

Every Go program is made up of packages.

You have probably noticed the package main at the top of all the programs you have been writing.

A package named "main" has an entrypoint at the main() function. A main package is compiled into an executable program.

A package by any other name is a "library package". Libraries have no entry point. Libraries simply export functionality that can be used by other packages. For example:

This program is an executable. It is a "main" package and imports from the fmt and math/rand library packages.

Package Names

Naming convention.

By convention , a package's name is the same as the last element of its import path. For instance, the math/rand package comprises files that begin with:

That said, package names aren't required to match their import path. For example, I could write a new package with the path github.com/mailio/rand and name the package random :

While the above is possible, it is discouraged for the sake of consistency.

One Package / Directory

A directory of Go code can have at most one package. All .go files in a single directory must all belong to the same package. If they don't an error will be thrown by the compiler. This is true for main and library packages alike.

Go programs are organized into packages . A package is a directory of Go code that's all compiled together. Functions, types, variables, and constants defined in one source file are visible to all other source files within the same package (directory) .

A repository contains one or more modules . A module is a collection of Go packages that are released together.

A Go repository typically contains only one module, located at the root of the repository.

A file named go.mod at the root of a project declares the module. It contains:

  • The module path
  • The version of the Go language your project requires
  • Optionally, any external package dependencies your project has

The module path is just the import path prefix for all packages within the module. Here's an example of a go.mod file:

Each module's path not only serves as an import path prefix for the packages within but also indicates where the go command should look to download it .

For example, to download the module golang.org/x/tools , the go command would consult the repository located at https://golang.org/x/tools .

An "import path" is a string used to import a package. A package's import path is its module path joined with its subdirectory within the module. For example, the module github.com/google/go-cmp contains a package in the directory cmp/ . That package's import path is github.com/google/go-cmp/cmp . Packages in the standard library do not have a module path prefix. – Paraphrased from Golang.org's code organization

Do I need to put my package on GitHub?

You don't need to publish your code to a remote repository before you can build it. A module can be defined locally without belonging to a repository. But it's a good habit to keep a copy of all your projects on a remote server, like GitHub.

How to Set Up Your Machine

Your machine will contain many version control repositories (managed by Git, for example).

Each repository contains one or more packages , but will typically be a single module .

Each package consists of one or more Go source files in a single directory.

The path to a package's directory determines its import path and where it can be downloaded from if you decide to host it on a remote version control system like Github or Gitlab.

A note on GOPATH

The $GOPATH environment variable will be set by default somewhere on your machine (typically in the home directory, ~/go ). Since we will be working in the new "Go modules" setup, you don't need to worry about that . If you read something online about setting up your GOPATH, that documentation is probably out of date.

These days you should avoid working in the $GOPATH/src directory. Again, that's the old way of doing things and can cause unexpected issues, so better to just avoid it.

Get into your workspace

Navigate to a location on your machine where you want to store some code. For example, I store all my code in ~/workspace , then organize it into subfolders based on the remote location. For example,

~/workspace/github.com/wagslane/go-password-validator = https://github.com/wagslane/go-password-validator

That said, you can put your code wherever you want.

How to Write Your First Local Go Program

Once inside your personal workspace, create a new directory and enter it:

Inside the directory declare your module's name:

Where {REMOTE} is your preferred remote source provider (i.e. github.com ) and {USERNAME} is your Git username. If you don't use a remote provider yet, just use example.com/username/hellogo

Print your go.mod file:

The Go Run Command

Inside hellogo , create a new file called main.go .

Conventionally, the file in the main package that contains the main() function is called main.go .

Paste the following code into your file:

Run the code

The go run command is used to quickly compile and run a Go package. The compiled binary is not saved in your working directory. Use go build instead to compile production executables.

I rarely use go run other than to quickly do some testing or debugging.

Further reading

Execute go help run in your shell and read the instructions.

The Go Build Command

go build compiles go code into an executable program.

Build an executable

Ensure you are in your hellogo repo, then run:

Run the new program:

Navigate out of your project directory:

Go has installed the hellogo program globally. Run it with:

Tip about "not found"

If you get an error regarding "hellogo not found" it means you probably don't have your Go environment setup properly. Specifically, go install is adding your binary to your GOBIN directory, but that may not be in your PATH .

You can read more about that here in the go install docs .

How to Create a Custom Go Package

Let's write a package to import and use in hellogo .

Create a sibling directory at the same level as the hellogo directory:

Initialize a module:

Then create a new file mystrings.go in that directory and paste the following code:

Note that there is no main.go or func main() in this package.

go build won't build an executable from a library package. However, go build will still compile the package and save it to our local build cache. It's useful for checking for compile errors.

How to Publish Remote Packages in Go

Let's learn how to use an open-source package that's available online.

A note on how you should publish modules

Be aware that using the "replace" keyword like we did in the last assignment isn't advised , but can be useful to get up and running quickly. The proper way to create and depend on modules is to publish them to a remote repository. When you do that, the "replace keyword can be dropped from the go.mod :

This works for local-only development

This works if we publish our modules to a remote location like Github as we should.

Best Practices with Go Packages

I’ve often seen, and have been responsible for, throwing code into packages without much thought. I’ve quickly drawn a line in the sand and started putting code into different folders (which in Go are different packages by definition) just for the sake of findability.

Learning to properly build small and reusable packages can take your Go career to the next level.

1. Hide internal logic

If you're familiar with the pillars of OOP, this is a practice in encapsulation .

Oftentimes an application will have complex logic that requires a lot of code. In almost every case the logic that the application cares about can be exposed via an API, and most of the dirty work can be kept within a package.

For example, imagine we are building an application that needs to classify images. We could build a package:

We create an API by only exposing the function(s) that the application-level needs to know about. All other logic is unexported to keep a clean separation of concerns. The application doesn’t need to know how to classify an image, just the result of the classification.

2. Don’t change APIs

The unexported functions within a package can and should change often for testing, refactoring, and bug fixing.

A well-designed library will have a stable API so that users aren’t receiving breaking changes each time they update the package version. In Go, this means not changing exported function’s signatures.

3. Don’t export functions from the main package

A main package isn't a library, there's no need to export functions from it.

4. Packages shouldn't know about dependents

Perhaps one of the most important and most broken rules is that a package shouldn’t know anything about its dependents. In other words, a package should never have specific knowledge about a particular application that uses it.

Further Reading

You can optionally read more here if you're interested.

Chapter 14 – Channels in Go

Concurrency.

Concurrency is the ability to perform multiple tasks at the same time. Typically, our code is executed one line at a time, one after the other. This is called sequential execution or synchronous execution .

concurrency

If the computer we're running our code on has multiple cores, we can even execute multiple tasks at exactly the same time. If we're running on a single core, a single code executes code at almost the same time by switching between tasks very quickly. Either way, the code we write looks the same in Go and takes advantage of whatever resources are available.

How does concurrency work in Go?

Go was designed to be concurrent, which is a trait fairly unique to Go. It excels at performing many tasks simultaneously and safely using a simple syntax.

There isn't a popular programming language in existence where spawning concurrent execution is quite as elegant, at least in my opinion.

Concurrency is as simple as using the go keyword when calling a function:

In the example above, doSomething() will be executed concurrently with the rest of the code in the function. The go keyword is used to spawn a new goroutine .

Channels are a typed, thread-safe queue. Channels allow different goroutines to communicate with each other.

Create a channel

Like maps and slices, channels must be created before use. They also use the same make keyword:

Send data to a channel

The <- operator is called the channel operator . Data flows in the direction of the arrow. This operation will block until another goroutine is ready to receive the value.

Receive data from a channel

This reads and removes a value from the channel and saves it into the variable v . This operation will block until there is a value in the channel to be read.

Blocking and deadlocks

A deadlock is when a group of goroutines are all blocking so none of them can continue. This is a common bug that you need to watch out for in concurrent programming.

Empty structs are often used as tokens in Go programs. In this context, a token is a unary value. In other words, we don't care what is passed through the channel. We care when and if it is passed.

We can block and wait until something is sent on a channel using the following syntax

This will block until it pops a single item off the channel, then continue, discarding the item.

Buffered Channels

Channels can optionally be buffered.

How to create a channel with a buffer

You can provide a buffer length as the second argument to make() to create a buffered channel:

Sending on a buffered channel only blocks when the buffer is full .

Receiving blocks only when the buffer is empty .

How to Close Channels

Channels can be explicitly closed by a sender :

How to check if a channel is closed

Similar to the ok value when accessing data in a map , receivers can check the ok value when receiving from a channel to test if a channel was closed.

ok is false if the channel is empty and closed.

Don't send on a closed channel

Sending on a closed channel will cause a panic. A panic on the main goroutine will cause the entire program to crash, and a panic in any other goroutine will cause that goroutine to crash.

Closing isn't necessary. There's nothing wrong with leaving channels open, they'll still be garbage collected if they're unused. You should close channels to indicate explicitly to a receiver that nothing else is going to come across.

Range Over a Channel

Similar to slices and maps, channels can be ranged over.

This example will receive values over the channel (blocking at each iteration if nothing new is there) and will exit only when the channel is closed.

Select from a channel

Sometimes we have a single goroutine listening to multiple channels and want to process data in the order it comes through each channel.

A select statement is used to listen to multiple channels at the same time. It is similar to a switch statement but for channels.

The first channel with a value ready to be received will fire and its body will execute. If multiple channels are ready at the same time one is chosen randomly. The ok variable in the example above refers to whether or not the channel has been closed by the sender yet.

Select Default

The default case in a select statement executes immediately if no other channel has a value ready. A default case stops the select statement from blocking.

Chapter 15 – Mutexes in Go

Mutexes allow us to lock access to data. This ensures that we can control which goroutines can access certain data at which time.

Go's standard library provides a built-in implementation of a mutex with the sync.Mutex type and its two methods:

We can protect a block of code by surrounding it with a call to Lock and Unlock as shown on the protected() method below.

It's good practice to structure the protected code within a function so that defer can be used to ensure that we never forget to unlock the mutex.

Mutexes are powerful. Like most powerful things, they can also cause many bugs if used carelessly.

Maps are not thread-safe

Maps are not safe for concurrent use! If you have multiple goroutines accessing the same map, and at least one of them is writing to the map, you must lock your maps with a mutex.

Why is it called a Mutex?

Mutex is short for mutual exclusion , and the conventional name for the data structure that provides it is "mutex", often abbreviated to "mux".

It's called "mutual exclusion" because a mutex excludes different threads (or goroutines) from accessing the same data at the same time.

Why use mutexes?

The principle problem that mutexes help us avoid is the concurrent read/write problem . This problem arises when one thread is writing to a variable while another thread is reading from that same variable at the same time .

When this happens, a Go program will panic because the reader could be reading bad data while it's being mutated in place.

mutex

Mutex example

The example above creates a map, then starts two goroutines which each have access to the map. One goroutine continuously mutates the values stored in the map, while the other prints the values it finds in the map.

If we run the program on a multi-core machine, we get the following output: fatal error: concurrent map iteration and map write

In Go, it isn’t safe to read from and write to a map at the same time.

Mutexes to the rescue

In this example, we added a sync.Mutex{} and named it mux . In the write loop, the Lock() method is called before writing, and then the Unlock() is called when we're done. This Lock/Unlock sequence ensures that no other threads can Lock() the mutex while we have it locked – any other threads attempting to Lock() will block and wait until we Unlock() .

In the reader, we Lock() before iterating over the map, and likewise Unlock() when we're done. Now the threads share the memory safely!

The standard library also exposes a sync.RWMutex

In addition to these methods:

The sync.RWMutex also has these methods:

The sync.RWMutex can help with performance if we have a read-intensive process. Many goroutines can safely read from the map at the same time (multiple Rlock() calls can happen simultaneously). However, only one goroutine can hold a Lock() and all RLock() 's will also be excluded.

Chapter 16 – Generics in Go

As we've mentioned, Go does not support classes. For a long time, that meant that Go code couldn't easily be reused in many circumstances.

For example, imagine some code that splits a slice into 2 equal parts. The code that splits the slice doesn't really care about the values stored in the slice. Unfortunately in Go we would need to write it multiple times for each type, which is a very un- DRY thing to do.

In Go 1.20 however, support for generics was released, effectively solving this problem!

Type Parameters

Put simply, generics allow us to use variables to refer to specific types. This is an amazing feature because it allows us to write abstract functions that drastically reduce code duplication.

In the example above, T is the name of the type parameter for the splitAnySlice function, and we've said that it must match the any constraint, which means it can be anything. This makes sense because the body of the function doesn't care about the types of things stored in the slice.

Why Generics?

Generics reduce repetitive code.

You should care about generics because they mean you don’t have to write as much code! It can be frustrating to write the same logic over and over again, just because you have some underlying data types that are slightly different.

Generics are used more often in libraries and packages

Generics give Go developers an elegant way to write amazing utility packages. While you will see and use generics in application code, I think it will much more common to see generics used in libraries and packages. Libraries and packages contain importable code intended to be used in many applications, so it makes sense to write them in a more abstract way. Generics are often the way to do just that!

Why did it take so long to get generics?

Go places an emphasis on simplicity. In other words, Go has purposefully left out many features to provide its best feature: being simple and easy to work with.

According to historical data from Go surveys , Go’s lack of generics has always been listed as one of the top three biggest issues with the language. At a certain point, the drawbacks associated with the lack of a feature like generics justify adding complexity to the language.

Constraints in Go

Sometimes you need the logic in your generic function to know something about the types it operates on. The example we used in the first exercise didn't need to know anything about the types in the slice, so we used the built-in any constraint:

Constraints are just interfaces that allow us to write generics that only operate within the constraint of a given interface type. In the example above, the any constraint is the same as the empty interface because it means the type in question can be anything .

How to create a custom constraint

Let's take a look at the example of a concat function. It takes a slice of values and concatenates the values into a string. This should work with any type that can represent itself as a string , even if it's not a string under the hood.

For example, a user struct can have a .String() that returns a string with the user's name and age.

Interface type lists

When generics were released, a new way of writing interfaces was also released at the same time!

We can now simply list a bunch of types to get a new interface/constraint.

How to Name Generic Types

Let's look at this simple example again:

Remember, T is just a variable name, We could have named the type parameter anything . T happens to be a fairly common convention for a type variable, similar to how i is a convention for index variables in loops.

This is just as valid:

Congratulations on making it to the end!

If you're interested in doing the interactive coding assignments and quizzes for this course you can check out the Learn Go course over on Boot.dev .

This course is a part of my full back-end developer career path , made up of other courses and projects if you're interested in checking those out.

If you want to see the other content I'm creating related to web development, check out some of my links below:

  • Lane's Podcast: Backend Banter
  • Lane on Twitter
  • Lane on YouTube

Instructor and founder of http://Boot.dev Whining about coding sins since 2011. Committing coding sins for the same. Follow me if you like back-end dev.

If you read this far, thank the author to show them you care. Say Thanks

Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started

IncludeHelp_logo

  • Data Structure
  • Coding Problems
  • C Interview Programs
  • C++ Aptitude
  • Java Aptitude
  • C# Aptitude
  • PHP Aptitude
  • Linux Aptitude
  • DBMS Aptitude
  • Networking Aptitude
  • AI Aptitude
  • MIS Executive
  • Web Technologie MCQs
  • CS Subjects MCQs
  • Databases MCQs
  • Programming MCQs
  • Testing Software MCQs
  • Digital Mktg Subjects MCQs
  • Cloud Computing S/W MCQs
  • Engineering Subjects MCQs
  • Commerce MCQs
  • More MCQs...
  • Machine Learning/AI
  • Operating System
  • Computer Network
  • Software Engineering
  • Discrete Mathematics
  • Digital Electronics
  • Data Mining
  • Embedded Systems
  • Cryptography
  • CS Fundamental
  • More Tutorials...
  • Tech Articles
  • Code Examples
  • Programmer's Calculator
  • XML Sitemap Generator
  • Tools & Generators

IncludeHelp

Golang Tutorial

  • Golang - Home
  • Golang - Keywords
  • Golang - Data Types
  • Golang - Variables
  • Golang - Constants
  • Golang - Program Structure
  • Golang - Comments
  • Golang - Naming a variable
  • Golang - Shorthand for Defining Multiple Variables/Constants
  • Golang - Find Type of Variable
  • Golang - Binary Literals
  • Golang - Octal Literals
  • Golang - Hexadecimal Literals
  • Golang - Type Casting or Type Conversion
  • Golang – Operators
  • Golang - Arithmetic Operators
  • Golang - Relational Operators
  • Golang - Logical Operators
  • Golang - Bitwise Operators
  • Golang - Assignment Operators
  • Golang - Miscellaneous Operators
  • Golang - if statement
  • Golang - if-else statement
  • Golang - if-else-if ladder statement
  • Golang - nested if statement
  • Golang - switch statement
  • Golang - select statement
  • Golang - Loops
  • Golang - Functions
  • Golang - Strings

Golang Reference

  • Go - builtin Package
  • Go - bytes Package
  • Go - fmt Package
  • Go - math Package
  • Go - os Package
  • Go - sort Package
  • Go - strconv Package
  • Go - strings Package
  • Go - unicode Package
  • Golang Programs
  • Golang Programs - Home
  • Golang - Basic Programs
  • Golang - Switch Statement Programs
  • Golang - goto Statement Programs
  • Golang - Looping Programs
  • Golang - Array Programs
  • Golang - String Programs
  • Golang - Structure Programs
  • Golang - User-defined Function Programs
  • Golang - Variadic Function Programs
  • Golang - Recursion Programs
  • Golang - Pointer Programs
  • Golang - Conversion Programs
  • Golang - Slices Programs
  • Golang - Date & Time Programs
  • Golang - Timers & Tickers Programs
  • Golang - Goroutines Programs
  • Golang - Reflection Programs
  • Golang - Maps Programs
  • Golang - Range Programs
  • Golang - Channels Programs
  • Golang - File Handling Programs
  • Golang - Buffered Input-Output Programs
  • Golang - Command-line Arguments Programs
  • Golang - Regular Expressions Programs
  • Golang - JSON Programs
  • Golang - os Package Programs
  • Golang - strconv Package Programs
  • Golang - log Package Programs
  • Golang - math/rand Package Programs
  • Golang - math/bits Package Programs
  • Golang - sync/atomic Package Programs
  • Golang - path/filepath Package Programs
  • Golang - syscall Package Programs
  • Golang - Signals Programs
  • Golang - Shell Script Programs

Golang Practice

  • Golang Interview Questions
  • Golang Find Output Programs
  • Golang Aptitude Questions

Golang Miscellaneous

  • Golang - Print Boolean Value
  • Golang - Print Double-quoted String
  • Golang - Convert From Int to Binary
  • Golang - Convert From Int to Octal
  • Golang - Convert From Int to Hex
  • Golang - Check if Structure is Empty
  • Golang - Check if Key Exists in Map
  • Golang - Return an Error
  • Golang - new() & make() Functions

Advertisement

Home » Golang

Golang Assignment Operators

Here, we are going to learn about the Assignment Operators in the Go programming language with examples. Submitted by IncludeHelp , on December 08, 2021

Assignment Operators

Assignment operators are used for assigning the expressions or values to the variable/ constant etc. These operators assign the result of the right-side expression to the left-side variable or constant. The " = " is an assignment operator. Assignment operators can also be the combinations of some other operators (+, -, *, /, %, etc.) and " = ". Such operators are known as compound assignment operators .

List of Golang Assignment Operators

Operator Description Example
x:=5
y:=3
Assignment (=) It assigns the result of the expression written on the right side to the variable written on the left side. x = 10 or x = y+10 or x = x+5, etc.
Add and Assignment (+=) It is the combination of '+' and '=' operators, it adds the given value with the current value of the variable and assigns it to the variable. x +=y is equivalent to x = x+y
Subtract and Assignment (-=) It is the combination of '-' and '=' operators, it subtracts the given value with the current value of the variable and assigns it to the variable. x -=y is equivalent to x = x-y
Multiply and Assignment (*=) It is the combination of '*' and '=' operators, it multiplies the given value with the current value of the variable and assigns it to the variable. x *=y is equivalent to x = x*y
Divide and Assignment (/=) It is the combination of '/' and '=' operators, it divides the given value with the current value of the variable and assigns it to the variable. x /=y is equivalent to x = x/y
Modulus and Assignment (%=) It is the combination of '%' and '=' operators, it finds the remainder of the current value of the variable with the given value and assigns it to the variable. x %=y is equivalent to x = x%y
Bitwise AND Assignment (&=) It is the combination of '&' and '=' operators, it performs the Bitwise AND operation with the current value of the variable and the given value and assigns the result to the variable. x &=y is equivalent to x = x&y
Bitwise OR Assignment (|=) It is the combination of '|' and '=' operators, it performs the Bitwise OR operation with the current value of the variable and the given value and assigns the result to the variable. x |=y is equivalent to x = x|y
Bitwise XOR Assignment (^=) It is the combination of '^' and '=' operators, it performs the Bitwise XOR operation with the current value of the variable and the given value and assigns the result to the variable. x ^=y is equivalent to x = x^y
Bitwise Left Shift Assignment (<<=) It is the combination of '<<' and '=' operators, it performs the Bitwise Left-shift operation with the current value of the variable and the given value and assigns the result to the variable. x <<=y is equivalent to x = x<<y
Bitwise Right Shift Assignment (>>=) It is the combination of '>>' and '=' operators, it performs the Bitwise Left-shift operation with the current value of the variable and the given value and assigns the result to the variable. x >>=y is equivalent to x = x>>y

Example of Golang Assignment Operators

The below Golang program is demonstrating the example of assignment operators.

Comments and Discussions!

Load comments ↻

  • Marketing MCQs
  • Blockchain MCQs
  • Artificial Intelligence MCQs
  • Data Analytics & Visualization MCQs
  • Python MCQs
  • C++ Programs
  • Python Programs
  • Java Programs
  • D.S. Programs
  • C# Programs
  • JavaScript Examples
  • jQuery Examples
  • CSS Examples
  • C++ Tutorial
  • Python Tutorial
  • ML/AI Tutorial
  • MIS Tutorial
  • Software Engineering Tutorial
  • Scala Tutorial
  • Privacy policy
  • Certificates
  • Content Writers of the Month

Copyright © 2024 www.includehelp.com. All rights reserved.

  • Data Types in Go
  • Go Keywords
  • Go Control Flow
  • Go Functions
  • GoLang Structures
  • GoLang Arrays
  • GoLang Strings
  • GoLang Pointers
  • GoLang Interface
  • GoLang Concurrency

Short Variable Declaration Operator(:=) in Go

Short Variable Declaration Operator(:=) in Golang is used to create the variables having a proper name and initial value. The main purpose of using this operator to declare and initialize the local variables inside the functions and to narrowing the scope of the variables. The type of the variable is determined by the type of the expression. var keyword is also used to create the variables of a specific type. So you can say that there are two ways to create the variables in Golang as follows:

  • Using the var keyword
  • Using the short variable declaration operator(:=)

In this article, we will only discuss the short variable declaration operator. To know about var keyword you can refer var keyword in Go . You can also read the difference between var keyword and short variable declaration operator to get a proper idea of using both.

Syntax of using short variable declaration operator:  

Here, you must initialize the variable just after declaration. But using var keyword you can avoid initialization at the time of declaration. There is no need to mention the type of the variable . Expression or value on the right-hand side is used to evaluate the type of the variable.

Example: Here, we are declaring the variables using short declaration operator and we are not specifying the type of the variable. The type of the variable is determined by the type of the expression on the right-hand side of := operator. 

 

Declaring Multiple Variables Using Short Declaration Operator (:=)

Short Declaration operator can also be used to declare multiple variables of the same type or different types in the single declaration. The type of these variables is evaluated by the expression on the right-hand side of := operator. 

Example:  

   

Important Points:  

  • Short declaration operator can be used when at least one of the variable in the left-hand side of := operator is newly declared. A short variable declaration operator behaves like an assignment for those variables which are already declared in the same lexical block. To get a better idea about this concept, let’s take an example. Example 1: Below program will give an error as there are no new variables in the left-hand side of the := operator .
 
./prog.go:17:10: no new variables on left side of :=   

Example 2: In the below program, you can see that the line of code geek3, geek2 := 456, 200 will work fine without any error as there is at least a new variable i.e. geek3 on the left-hand side of := operator.

 
  • Go is a strongly typed language as you cannot assign a value of another type to the declared variable.    Example:
   
./prog.go:16:4: no new variables on left side of :=  ./prog.go:16:7: cannot use “Golang” (type string) as type int in assignment   
  • In a short variable declaration, it is allowed to initializing a set of variables by the calling function which returns multiple values. Or you can say variables can also be assigned values that are evaluated during run time.  Example:

Local Variables or Global Variables?

With the help of short variable declaration operator(:=) you can only declare the local variable which has only block-level scope. Generally, local variables are declared inside the function block. If you will try to declare the global variables using the short declaration operator then you will get an error.

Example 1:  

             
./prog.go:15:1: syntax error: non-declaration statement outside function body   
           

Output:  

Please Login to comment...

Similar reads.

  • Go Language
  • Go-Operators
  • Top Android Apps for 2024
  • Top Cell Phone Signal Boosters in 2024
  • Best Travel Apps (Paid & Free) in 2024
  • The Best Smart Home Devices for 2024
  • 15 Most Important Aptitude Topics For Placements [2024]

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

Source file src / go / types / assignments.go

View as plain text

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Array Assignment in Go: Content copy or Content pointer copy

While learning nuances of array data structure in Go I came across an interesting confusion. I have learnt from blog.golang.org that -

when you assign or pass around an array value you will make a copy of its contents.

To check this myself I wrote the following piece of code:

Doing exactly the same thing in Java I got same internal object address for x and y as expected.

Go Code: https://play.golang.org/p/04l0l84eT4J

Java code: https://pastebin.ubuntu.com/p/S3fHMTj5NC/

shakhawat's user avatar

is a slice , not an array .

If you make x an array:

then you'll see the results you're expecting:

produces output like this:

https://play.golang.org/p/-3ZNPwlD1WT

mu is too short's user avatar

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged arrays go or ask your own question .

  • The Overflow Blog
  • At scale, anything that could fail definitely will
  • Featured on Meta
  • Announcing a change to the data-dump process
  • Bringing clarity to status tag usage on meta sites
  • What does a new user need in a homepage experience on Stack Overflow?
  • Feedback requested: How do you use tag hover descriptions for curating and do...
  • Staging Ground Reviewer Motivation

Hot Network Questions

  • Whats the safest way to store a password in database?
  • Does an unseen creature with a burrow speed have advantage when attacking from underground?
  • Word for someone who tries to make others hate each other
  • Why is the stall speed of an aircraft a specific speed?
  • How do Trinitarian Christians defend the unfalsifiability of the Trinity?
  • Sum of reciprocals of rough numbers
  • Best way to explain the thinking steps from x² = 9 to x=±3
  • How to find the x-coordinate of the point circled(non-differentiable points) in this trigonometric function graph?
  • MANIFEST_UNKNOWN error: OCI index found, but Accept header does not support OCI indexes
  • How should I secure ceiling drywall with no edge backing?
  • How do I apologize to a lecturer
  • How to reconcile the effect of my time magic spell with my timeline
  • If a Palestinian converts to Judaism, can they get Israeli citizenship?
  • best way to double-bend arrows smoothly
  • Does an airplane fly less or more efficiently after an mid-flight engine failure?
  • Not a cross, not a word (number crossword)
  • What would happen if the voltage dropped below one volt and the button was not hit?
  • Admissibility of withdrawn confession
  • Proof of the principle of explosion
  • Lore reasons for being faithless
  • Why is there so much salt in cheese?
  • What rules of legal ethics apply to information a lawyer learns during a consultation?
  • When trying to find the quartiles for discrete data, do we round to the nearest whole number?
  • How to resolve hostname by mDNS?

golang assignment

IMAGES

  1. Golang Variables Declaration, Assignment and Scope Tutorial

    golang assignment

  2. Golang Tutorial #3

    golang assignment

  3. Ultimate GoLang Beginner's Cheat Sheet

    golang assignment

  4. Basics of Go: Variables and it's Magic

    golang assignment

  5. Getting Started with Golang: A Beginner’s Guide

    golang assignment

  6. Getting started with Golang: A tutorial for beginners

    golang assignment

VIDEO

  1. Virtual Programming Lab and Go Auto-Grading Example

  2. Intro to Golang course: slides and examples

  3. Map-Reduce Golang Assignment Test Cases Passed

  4. Brutally Honest Review Of A Golang Newbie's Rejected Code

  5. Golang backend assignment Demo

  6. 3 Key Updates from Go 1.22

COMMENTS

  1. syntax

    A short variable declaration uses the syntax: ShortVarDecl = IdentifierList ":=" ExpressionList . It is a shorthand for a regular variable declaration with initializer expressions but no types: "var" IdentifierList = ExpressionList . Assignments. Assignment = ExpressionList assign_op ExpressionList . assign_op = [ add_op | mul_op ] "=" .

  2. A Tour of Go

    Inside a function, the := short assignment statement can be used in place of a var declaration with implicit type. Outside a function, every statement begins with a keyword (var, func, and so on) and so the := construct is not available. < 10/17 >. short-variable-declarations.go Syntax Imports.

  3. Difference between := and = operators in Go

    from the reference doc : (tour.golang.org) Inside a function, the := short assignment statement can be used in place of a var declaration with implicit type. Outside a function, every construct begins with a keyword (var, func, and so on) and the := construct is not available. answered Aug 23, 2013 at 8:05.

  4. Go Assignment Operators

    Assignment operators are used to assign values to variables. In the example below, we use the assignment operator (=) to assign the value 10 to a variable called x: Example. package main import ("fmt") func main() { var x = 10 fmt.Println(x)}

  5. How To Use Variables and Constants in Go

    The phrase i := 1032049348 is a declaration and assignment statement that consists of a few parts: the variable name (i) ... (or GoLang) is a modern programming language originally developed by Google that uses high-level syntax similar to scripting languages. It is popular for its minimal syntax and innovative handling of concurrency, as well ...

  6. The Go Programming Language Specification

    The multi-valued assignment form of the receive operator reports whether a received value was sent before the channel was closed. A single channel may be used in send statements, receive operations, and calls to the built-in functions cap and len by any number of goroutines without further synchronization. Channels act as first-in-first-out queues.

  7. Go Operators (With Examples)

    In Go, we can also use an assignment operator together with an arithmetic operator. For example, number := 2 number += 6. Here, += is additional assignment operator. It first adds 6 to the value of number (2) and assigns the final result (8) to number. Here's a list of various compound assignment operators available in Golang.

  8. = vs

    This post will briefly describe the differences between the assignments and short variable declarations in Go. It assumes that you have completed A Tour of Go and have consulted relevant sections of Effective Go and the target audience is primarily newcomers to the Go programming language.. The assignment operator (=) is used to perform assignments (i.e. to assign or reassign values to already ...

  9. Golang Variables Declaration, Assignment and Scope Tutorial

    Golang Variable Declaration. Lets look at the declaration of an integer type: var i int = 5. This declares a variable named i of type int with a value of 5. The Go compiler is pretty smart, so you can sometimes omit some declarations. For example: var i = 5. The compiler infers that 5 is of type int, and so assigns that type to i.

  10. Re-declaration and Re-assignment of variables in Golang

    In the first statement, the variable is declared, whereas it is only re-assigned in the second statement. Now, what is happening here, the second statement is re-assigning a new value to the ...

  11. Go

    The following table lists all the assignment operators supported by Go language −. Operator. Description. Example. =. Simple assignment operator, Assigns values from right side operands to left side operand. C = A + B will assign value of A + B into C. +=. Add AND assignment operator, It adds right operand to the left operand and assign the ...

  12. The Golang Handbook

    The value of an initialized variable with no assignment will be its zero value. Short Variable Declaration. Inside a function (even the main function), the := short assignment statement can be used in place of a var declaration. The := operator infers the type of the new variable based on the value. var empty string. Is the same as: empty := ""

  13. A Tour of Go

    If with a short statement. Like for, the if statement can start with a short statement to execute before the condition. Variables declared by the statement are only in scope until the end of the if. (Try using v in the last return statement.) < 6/14 >. if-with-a-short-statement.go Syntax Imports. 21.

  14. Golang Assignment Operators

    Assignment operators are used for assigning the expressions or values to the variable/ constant etc. These operators assign the result of the right-side expression to the left-side variable or constant. The " = " is an assignment operator. Assignment operators can also be the combinations of some other operators (+, -, *, /, %, etc.) and " = ".

  15. Go maps in action

    A two-value assignment tests for the existence of a key: i, ok := m["route"] In this statement, the first value (i) is assigned the value stored under the key "route". If that key doesn't exist, i is the value type's zero value (0). The second value (ok) is a bool that is true if the key exists in the map, and false if not.

  16. How To Do Math in Go with Operators

    The = assignment operator assigns the value on the right to a variable on the left. For example, ... (or GoLang) is a modern programming language originally developed by Google that uses high-level syntax similar to scripting languages. It is popular for its minimal syntax and innovative handling of concurrency, as well as for the tools it ...

  17. Short Variable Declaration Operator(:=) in Go

    Last Updated : 17 May, 2021. Short Variable Declaration Operator (:=) in Golang is used to create the variables having a proper name and initial value. The main purpose of using this operator to declare and initialize the local variables inside the functions and to narrowing the scope of the variables. The type of the variable is determined by ...

  18. - The Go Programming Language

    go.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more.

  19. go

    12. One possible way to do this in just one line by using a map, simple I am checking whether a > b if it is true I am assigning c to a otherwise b. c := map[bool]int{true: a, false: b}[a > b] However, this looks amazing but in some cases it might NOT be the perfect solution because of evaluation order.

  20. go

    No. Only one 'simple statement' is permitted at the beginning of an if-statement, per the spec. The recommended approach is multiple tests which might return an error, so I think you want something like: genUri := buildUri() if err := setRedisIdentity(genUri, email); err != nil {. return "", err.

  21. Array Assignment in Go: Content copy or Content pointer copy

    Array Assignment in Go: Content copy or Content pointer copy. Ask Question Asked 6 years, 5 months ago. Modified 3 years ago. Viewed 3k times 0 While learning nuances of array data structure in Go I came across an interesting confusion. I have learnt from blog.golang.org that - when you assign or pass around an array value you will make a copy ...