# Golang: Variables and Types

Understanding and creating variables and their types in Golang

#go

## Introduction

In the third part of the series, we will be covering the fundamentals for learning any programming language i.e. variables and data types. We will be covering from data types to variable declaration. We won't be seeing each and every detail related to the data types as some of them require a knowledge of loops and other topics, so that can be left for the different part.

## Types in golang

In Golang there are 3 major types : Numeric, Bool and String. Further we also have specific types for the three data types like int, float, rune, byte, etc. We will first see how to declare a simple variable and then explore the data types in Golang.

var name string


This the variable declaration in Golang, we have the keyword  var  similar to Javascript but we optionally have to specify the type of the variable if we are not immediately assigning/defining it a value.

To assign variable values, we can write the datatype of the assigned value but it is optional as the go compiler will know the datatype according to the assigned value. Further you cannot change the type of that variable once it is initialized.

var name string = "Gopher"

OR

var name string
name = "Gopher"

OR

var name = "Gopher"


We also have  const  for assigning constant values to a particular value set. You cannot change the value for a constant type, doing this will result in compile time error. An important property of  const  can be noted here, if you simply declare a  const  without initializing the value and try to access that constant, the go-compiler will throw an compilation error.

const name string = "David"

OR

const name string
name = "Calvin"

OR

const name = "Smith"


By default, the values for string is an empty string  ""  , for integer and float it is  0  and for bool it is  false  .

Each of these are valid declaration of variables in golang. Let's now dive into the data types and follow up with variable declaration in detail later.

Numeric String Bool
int string bool
float
complex
rune
byte

### Numeric

Let's first explore the  numeric  data types in golang as you have guessed correctly, we have  int  and  float  as distinct categories but further we also have fine grained storage types for both of the types.

#### Integer

In integers as well we have two categories  signed  and  unsigned  , we can basically store only positive integers in  unsigned  integers giving us an extra bit to play with.

For Integers, we have specific data storage types depending on the bits it can store like  int8  for storing 8 bit integers,  int16  for storing 16 bit integer value,  int32  and  int64  for the given number of bits in the integer. Similarly we will have these storage based integer values for unsigned integers like  uint8  ,  uint16  ,  uint32  and  uint64  . We can basically store double amount of positive integers in unsigned integers as  uint  than in signed integers  int  , this is because the most significant bit is not used as a sign bit since all values in the variable are positive and hence no sign bit is required.

var likes int = 140
fmt.Println(likes)

$go run int.go 140  var age int8 = 140 fmt.Println("Age = ",age)  $ go run int.go
# command-line-arguments
.\int.go:6:9: constant 140 overflows int8


This will give us an error as  140  is above the limit for  int8  . So, unless you have specific requirements as storage limitation, you should be using  int  as the default data type for storing integers.

So, we need to define variables as per the limits to which we are going to use them, if you just specify  int  the type will be selected based on your operating system, if it is  32bit  , it will take  int32  , for  64bit  OSes it will take as  int64  integer. If you define a variable with let say  16  bit storage and if it exceeds the limit for  16  bit storage, it would give a  overflow limit  error.

Below are the limits for all the integer types in Golang:

uint8 ->  0  to  255
uint16 ->  0  to  65535
uint32 ->  0  to  4294967295
uint64 ->  0  to  18446744073709551615

int8 ->  -128  to  127
int16 ->  -32768  to  32767
int32 ->  -2147483648  to  2147483647
int64 ->  -9223372036854775808  to  9223372036854775807


If you want to reality check for the boundary values of this data types, you can code a program in  go  as below:

• To find the maximum value of uint, we can flip all the bits in  0  to get all the set bits in the integer thus we use  ^  operator.
• To find the maximum value for signed integers, we can right shit one bit so as to unset the sign bit.
• The minimum value for uint is the default value  0  .
• The minimum value for int can be calculated by subtracting one from the negative of the max limit.
package main

import (
"fmt"
)

func main() {
var min_uint = 0
var max_uint8 uint8 = ^uint8(0)
var max_uint16 uint16 = ^uint16(0)
var max_uint32 uint32 = ^uint32(0)
var max_uint64 uint64 = ^uint64(0)

var max_int8 int8 = int8(max_uint8>>1)
var min_int8 int8 = -max_int8 - 1
var max_int16 int16 = int16(max_uint16>>1)
var min_int16 int16 = -max_int16 - 1
var max_int32 int32 = int32(max_uint32>>1)
var min_int32 int32 = -max_int32 - 1
var max_int64 int64 = int64(max_uint64>>1)
var min_int64 int64 = -max_int64 - 1

fmt.Println("uint8 -> ", min_uint, " to ", max_uint8)
fmt.Println("uint16 -> ", min_uint, " to ", max_uint16)
fmt.Println("uint32 -> ", min_uint, " to ", max_uint32)
fmt.Println("uint64 -> ", min_uint, " to ", max_uint64)
fmt.Println("")
fmt.Println("int8 -> ", min_int8, " to ", max_int8)
fmt.Println("int16 -> ", min_int16, " to ", max_int16)
fmt.Println("int32 -> ", min_int32, " to ", max_int32)
fmt.Println("int64 -> ", min_int64, " to ", max_int64)
}


This was the basic overview of Integers in Golang.

Though rune and byte are Integer aliases, we will explore them in the String section as they make a lot of sense over there.

#### Float

Similar to integers, we also have floats in the numeric category. A float is a numeric data type that can allow numbers with decimal values. A simple float can be of either  float32  or  float64  . The two types are defined as the precision of the decimal values. Obliviously, the  float64  type is more precise than the counterpart and is also the default type assigned if not provided.

const percent = 30.5
fmt.Println(percent+50)


You optionally provide the  float32  type to have a bit less precision than usual using the  float32  keyword as follows:

const percent float32 = 46.34
fmt.Println(percent - 3.555)


The floating value precision of the float types in golang are as follows:

float32   -->   -3.4e+38 to 3.4e+38.
float64   -->   -1.7e+308 to +1.7e+308.


As quite logical reasons, the precision is almost double in the  float64  compared to  float32  . If we try to add(any operation) a  float64  number with a  flaot32  , we get an error as performing operations on two differently stored types can't be operated.

#### Complex Numbers

We also have complex numbers in golang. This are the numbers which deal with a real and a imaginary numbers. We initialize the complex variable using the  complex  function which takes two parameters the  real  part and the  imagianry  part. Both the parts or numbers are stored as float in the complex data type.

So, since golang has  float32  and  float64  data types, we will have  complex64  and  complex128  as complex types. Since we are storing two  flaot64  , it has a  complex128  type and  complex64  for both parts as  float32  . Here as well, you cannot store the two parts(real and imaginary) as different float types i.e. You need to have both real and imaginary as either  flaot32  or  flaot64  .

var percent = 30.738
var f = 4.545
var comp1 = complex(f, percent)
var comp2 = complex(percent, f)
fmt.Println(comp1 - comp2)

(-26.192999999999998+26.192999999999998i)


Golang automatically adds the  i  or iota in the complex/imaginary part for better readability.

### Strings

We can now move onto the  string  data type in golang. It has several data types like  byte  ,  rune  ,  string  . In golang,  byte  and  rune  store individual characters whereas  string  can hold multiple characters.

#### Byte

A byte in golang is an unsigned 8 bit integer, which means it can hold numeric data from 0 to 255. So how is this displaying characters if it stores integer. Well, because each number it stores is mapped to the ASCII character set which is used to represent characters.

A byte can be stored in a single quote  ''  , if we use double quotes  ""  , the variable is considered as string if we aren't specifying the data type.

const c byte = 't'
fmt.Println(c)

$go run byte.go 116  This gives the output as a number between 0 and 255 depending on the character which you have stored. To print the actual character you need to type caste into a string like: const c byte = 't' fmt.Printf("Character = %c \nInteger value = %d\n", c, c)  $ go run byte.go
Character = t
Integer Value = 116


We can get the character equivalent of the byte representation number using the Printf function and the  %c  place holder for a character. The  \n  is used to end the line just for displaying proper output.

We can even store numbers between  0  and  255  as it is internally an  uint8  .

#### Rune

A rune is extended type of byte as it stores  int32  numbers and hence it represents  Unicode  characters. This is the default type if you do not specify  byte  and use single quotes to assign a character. Using rune, we can assign it an unicode characters to display some rich characters and literals like emoji or expressions.

var smiley_emoji = '\u263A'
fmt.Printf("Smiley Emoji --> %c", smiley_emoji)


So, rune is pretty amazing type to play with characters in golang. As it is a default type assigned against byte if not provided while assignment.

#### String

Strings are basically a slice(list) of bytes. Each character in a string is a byte. By default the string will be empty if you don't initialize it with a value.

const language string
language = "C++"

OR

const language string= "Python"

OR

const language = "Javascript"


We can even access particular character in the string using it's index.

const code = "12AB34CD"
fmt.Println(code[6])

$go run string.go 67  This gives us a integer as we are accessing the byte from the string using its index. Thus, we can use  %c  in the  Printf  function to format and print the equivalent characters of the byte. const code = "12AB34CD" fmt.Printf("2nd Character in string = %c\n", code[4])  $ go run string.go
2nd Character in string = A


We can also declare strings using backticks/backquotes or whatever you call it (), assigning string with this allows us to write multi line string.

var statement = This is the first line
The next line
The last line

fmt.Println(statement)

$go run str-backticks.go This is the first line The next line The last line  Further in the loop article we will see how to loop/iterate over a string. ### Boolean This type is used to store either  true  or  false  in golang. The default value of a boolean variable is  false  . var power bool fmt.Println(power)  $ go run bool.go
false


We can assign the variable as either  true  or  false  .

const result = true
fmt.Printf("The statement is %t", result)

$go run bool.go The statement is true  So, using the  %t  we can print the value of a boolean value in golang in the  Printf  function. ## Creating Variables Now, we have familiar with data types in golang, we can more expressively create, declare, initialize variables in golang. There are 3-4 primary ways to define a variable most of which we have already seen. ### Declaring a Variable We can declare a variable without assigning it any value but for that we need to then provide the data type, this can be done using the following command: var expereience int expereience = 2  We can even use  const  for constant value in the given scope. Here, we can even declare multiple variables by separating each variable/constant with comma  ,  which can be done as follows: var a, b, c int OR const i, j, k bool  ### Defining and Initializing at the same time We can initialize a variable/constant in golang by explicitly giving it a value. We can do that by using  var  for variable value or  const  for a constant value. We can optionally provide the data type at this moment as golang will automatically detect the type and assign the memory according to the value given. var place string = "home"  Here, there is no compulsion to provide the  datatype  as the compiler will be able to know it from the asisgned value. Though if you want to provide a non-default value you can specify the datatype. ### Declaring Multiple Variables We can assign multiple variables at once by separating them with comma  ,  . The variable name to the left and the values to the right needs to separated with comm on both sides. var x, y, z = 100, '#', "days" fmt.Printf(" x = %d \n y = %c \n z = %s \n",x,y,z)  $ go run multiplvar.go
x = 100
y = #
z = daysofcode


We can are declaring and assigning multiple variables, the  x  variable is assigned an integer value,  y  with a  rune  (by default) and  z  with a string. We are using  Printf  function with place holders for int  %d  , rune/byte  %c  and string as  %s  . The  \n  is for a new line.

If we want to assign the variables with a particular data type, we can use the var keyword as a list of values.

var (
x int8 = 100
y byte = '#'
z =  "daysofcode"
)

fmt.Printf(" x = %T \n y = %T \n z = %T \n",x,y,z)

$go run multiplvar.go x = int8 y = uint8 z = string  This is not only limited to  var  we can also use  const  to declare multiple constants with type constraint. Also, note we are using the  %T  placeholder for getting the type of the data stored in the variable. Also, we can define(declare and initialize) multiple variable with same data type with command separated as follows: var pi, e, G float32 = 3.141, 2.718, 6.67e-11 var start, end byte = 65, 90 fmt.Println(pi, e, G) fmt.Printf("%c %c\n",start, end)  $ go run multp.go
3.141 2.718 6.67e-11
A Z


### Assigning Variable using Walrus Operator (Shorthand Declaration)

We can skip usign  var  or the  datatype  by using the  :=  walrus operator. This type of assignment using  walruns  operator can only be allowed in the function body and not anywhere else, in the global scope this type of assignment is not allowed.

place := "school"


This is such a simple shorthand for assigning variables though only in a function body.

Also, multiple variable declaration is possible with walrus operator.

x, y, z := "foo", 32, true
fmt.Println(x, y, z)
fmt.Printf("%T %T %T", x, y, z)

\$ go run walrus.go
foo 32 true
string int bool
`

Links to all code and links are visible on the GitHub repository.

## Conclusion

So, from this part of the series, we were able to understand variables and the various data types in Golang. Though we didn't got too much in detail still we can find ourselves a bit comfortable in understanding basic go scripts. In the next section, we will looking into conditional statements and loops. This would give a good grasp on iterating over a string and even learn arrays(just the basics) we will explore Arrays and slices(remember strings?) after that.

So, if you have any questions, suggestions, or feedback please let me know in the comments or on the social handles. See you next time, Happy Coding :)