Go basics
last modified July 23, 2026
In this article we cover the basic programming concepts of Go.
Go is an open source, statically typed, compiled language created at Google. It is designed for building simple, reliable, and efficient software.
Identifiers
Identifiers are names given to variables, functions, parameters, or other program entities. They consist of alphanumeric characters and underscores but cannot begin with a number or contain whitespace.
Identifiers are case sensitive: Name, name, and
NAME are three distinct names. Language keywords (such as
if, for, func) cannot be used as
identifiers.
Go white space
White space separates tokens in Go source code and improves readability.
var i int = 0
White space is required in some places — for instance between a variable name and its type. In other places it is forbidden; for example, identifiers and keywords cannot contain spaces.
var i int=1 var j int = 2 var k int = 3
The amount of white space between tokens does not matter to the compiler. Nevertheless, consistent use of white space is good practice.
First example
We create our first example.
$ mkdir first $ cd first
We create a project directory and relocate there.
$ go mod init zetcode.com/first
We initiate a Go module.
package main
import "fmt"
func main() {
fmt.Println("Go first example")
}
This is a simple Go program, which prints a message to the console.
package main
Go code is organized in packages. Programs start running in the
main package.
import "fmt"
Packages are included into the program with the import keyword.
The fmt package contains functions for formatted I/O.
func main() {
Inside the main package, the main function is the entry point of a Go program.
Functions are created with the func keyword.
fmt.Println("Go first example")
From the fmt package, we use the Println function
to display a message. Notice that the statement is not terminated with semicolon
as in languages such as Java, C, or C#.
$ go run main.go Go first example
We compile and execute the program in one go with go run command.
Comments
Comments are used by humans to clarify source code. There are two types of comments in Go: single line comments (//) and multi-line comments (/* */).
package main
import "fmt"
/*
This is comments.go
Author: Jan Bodnar
ZetCode 2024
*/
// Program starts here
func main() {
fmt.Println("Go first example")
}
In the code example, we have a multi-line and a single line comment. Comments are ignored by the compiler.
Variables
A variable is used to store a value. It is a label given to the value. Go uses
the var keyword to declare a list of variables. We can also use the
:= shorthand syntax to declare variables.
Variables can hold values of different data types. A data type is a set of values and the allowable operations on those values. In many cases, Go can infer the data type from the right side of the assignment.
package main
import "fmt"
func main() {
var i int = 1
var w float64 = 12.5
fmt.Println(i, w)
}
In the code example, we declare and initialize two variables and then we print them. The first variable holds an integer, the second a float. The data types follow variable names in Go.
Type inference
Go can infer the data type from the right side of the assignment.
package main
import (
"fmt"
"reflect"
)
func main() {
var name = "John Doe"
var age = 34
fmt.Println(reflect.TypeOf(name))
fmt.Println(reflect.TypeOf(age))
fmt.Printf("%s is %d years old\n", name, age)
}
In the code example, we define two variables without specifying their data type. The data types are inferred.
var name = "John Doe" var age = 34
In order for the inference to work, the variables must be initialized.
fmt.Println(reflect.TypeOf(name)) fmt.Println(reflect.TypeOf(age))
With the help of the TypeOf function from the reflect
package, we print the data types of the two variables.
$ go run main.go string int John Doe is 34 years old
Shorthand variable declaration
Inside a function, the := short assignment statement can be used in
place of a var declaration with implicit type.
package main
import "fmt"
func main() {
name := "John Doe"
age := 34
fmt.Printf("%s is %d years old\n", name, age)
}
The example declares two variables with the shorthand notation.
Zero values
In Go, variables declared without an explicit initial value are automatically set to their zero value. This is a distinct feature of Go that helps prevent uninitialized variable bugs.
package main
import "fmt"
func main() {
var (
name string
age int
price float64
ok bool
)
fmt.Printf("%q %d %.2f %v\n", name, age, price, ok)
}
The example declares four variables without initialization and prints their
zero values: an empty string for string, 0 for
int, 0.00 for float64, and
false for bool.
$ go run main.go "" 0 0.00 false
Constants
Constants are declared with the const keyword. Their value must be
known at compile time and cannot change during program execution.
package main
import "fmt"
func main() {
const pi = 3.14159265
const maxRetries = 3
fmt.Println(pi, maxRetries)
}
The example declares two constants. Unlike variables, constants can be declared
without a type — the type is inferred from the value. Constants cannot use the
:= shorthand.
$ go run main.go 3.14159265 3
User input
The Scanf function scans text read from standard input, storing
successive space-separated values into successive arguments as determined by the
format. It returns the number of items successfully scanned.
package main
import "fmt"
func main() {
var name string
fmt.Print("Enter your name: ")
fmt.Scanf("%s", &name)
fmt.Println("Hello", name)
}
The example prompts the user to enter his name.
var name string
We define a string variable.
fmt.Scanf("%s", &name)
The entered value is stored into the name variable.
$ go run main.go Enter your name: Robert Hello Robert
We run the program and enter a name.
Conditionals
Conditionals are created with the if, else if, and
else keywords.
package main
import (
"fmt"
"math/rand"
)
func main() {
num := -5 + rand.Intn(10)
if num > 0 {
fmt.Println("The number is positive")
} else if num == 0 {
fmt.Println("The number is zero")
} else {
fmt.Println("The number is negative")
}
}
In this example, we generate random values between -5 and 4. With the help of the conditionals, we print a message for all three options.
For loop
The for statement specifies repeated execution of a block.
package main
import "fmt"
func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
}
This is the classic C-style for statement. The program calculates the sum of values 1..9.
for i := 0; i < 10; i++ {
sum += i
}
The for statement consists of three parts: the initialization, the condition, and the increment. The initialization part is executed only once. The body of the for statement is executed when the condition is true. If the condition returns false, the for loop is terminated.
After the statements in the block are executed, the for loop switches to the third part, where the counter is incremented. The cycle continues until the condition is not true anymore. Note that is it possible to create endless loops.
$ go run main.go 45
The sum of values 1..9 is 45.
The following example uses the for loop with the
range keyword.
package main
import "fmt"
func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
sum := 0
for _, num := range nums {
sum += num
}
fmt.Println(sum)
}
This example calculates the sum of array values.
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
We define an array of values.
for _, num := range nums {
sum += num
}
We iterate over the array with the range clause. The
range returns the index and the value in each iteration. Since we
do not use the index, we specify the discard _ operator. (The
Golang documentation calls it the blank identifier.)
Go has no while keyword — a while loop is a control
flow construct, very common in other languages, that repeats a block of code as
long as a given condition remains true. In Go, the for statement
with only a condition serves the same purpose.
package main
import "fmt"
func main() {
i := 0
for i < 5 {
fmt.Println(i)
i++
}
}
The example uses for with just a condition, behaving like a
while loop from other languages.
$ go run main.go 0 1 2 3 4
Switch statement
Go switch statement provides a multi-way execution. An expression or type specifier is compared to the cases inside the switch to determine which branch to execute. Unlike in other languages such as C, Java, or PHP, each case is terminated by an implicit break; therefore, we do not have to write it explicitly.
The default statement can be used for a branch that is executed, when no other cases fit. The default statement is optional.
package main
import (
"fmt"
"runtime"
)
func main() {
os := runtime.GOOS
switch os {
case "windows":
fmt.Println("Windows")
case "darwin":
fmt.Println("MAC operating system")
case "linux":
fmt.Println("Linux")
default:
fmt.Printf("%s.\n", os)
}
}
The GOOS environment variable is the running program's operating
system target: one of darwin, freebsd, linux, and so on. Based on the value of
the variable, we print the OS version.
$ go run main.go Linux
Command-line arguments
Command-line arguments are options and data that are passed to programs. We usually pass arguments to console programs, but sometimes we pass arguments to GUI programs as well.
The os.Args holds the command-line arguments. The first value in
this slice is the name of the program, while the os.Args[1:]
holds the arguments to the program. The individual arguments are accessed with
indexing operation.
package main
import (
"fmt"
"os"
"reflect"
)
func main() {
prgName := os.Args[0]
fmt.Printf("The program name is %s\n", prgName)
names := os.Args[1:]
fmt.Println(reflect.TypeOf(names))
for _, name := range names {
fmt.Printf("Hello, %s!\n", name)
}
}
The example receives command-line arguments.
prgName := os.Args[0]
fmt.Printf("The program name is %s\n", prgName)
We get and print the first argument, which is the program name.
names := os.Args[1:]
We get all the received arguments.
fmt.Println(reflect.TypeOf(names))
We print the type which holds the arguments (slice).
for _, name := range names {
fmt.Printf("Hello, %s!\n", name)
}
We go through the arguments and build a message from each of them.
$ go build main.go $ ./main Jan Peter Lucia The program name is main []string Hello, Jan! Hello, Peter! Hello, Lucia!
We build the program and run it. We pass the program three names on the command line.
Functions
A function is a mapping of zero or more input parameters to zero or more output parameters. Go functions are first-class citizens. Functions can be assigned to variables, passed as arguments to functions or returned from functions.
Functions in Go are created with the func keyword. We use the return keyword to return values from functions. The body of the function consists of statements that are executed when the function is called. The body is delimited with a pair of curly brackets {}. To call a function, we specify its name followed by round brackets (). A function may or may not take parameters.
package main
import "fmt"
func main() {
x := 4
y := 5
z := add(x, y)
fmt.Printf("Output: %d\n", z)
}
func add(a int, b int) int {
return a + b
}
In the code example, we define a function which adds two values.
z := add(x, y)
We call the add function; it takes two parameters. The computed
value is passed to the z variable.
func add(a int, b int) int {
return a + b
}
We define the add function. The parameters of the function are
separated with comma; each parameter name is followed with its data type.
After the parameters, we specify the return value type. The statements that are
executed when the function is called are placed between curly brackets.
The result of the addition operation is returned to the caller with the
return keyword.
$ go run main.go Output: 9
Multiple return values
Go functions can return multiple values. This is commonly used for returning both a result and an error.
package main
import (
"errors"
"fmt"
)
func main() {
val, err := divide(10, 3)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("Result: %.2f\n", val)
}
}
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
The divide function returns both a value and an error. If the
divisor is zero, it returns an error; otherwise it returns the quotient. This
pattern is idiomatic Go.
$ go run main.go Result: 3.33
Source
The Go Programming Language Specification
In this article we have covered the basics of Go language.
Author
List all Go tutorials.