Skip to main content

Command Palette

Search for a command to run...

First Break: Getting Started with Go

Updated
9 min read
First Break: Getting Started with Go
J

Hacking Lover, Scripting Addict -my own life is a script after all-

Hi everyone! this is Jimmy , and this is the very first article in my series “Breaking Things with Go.” In this series, I document my journey through Jon Bodner’s Second Edition: Learning Go – An Idiomatic Approach to Real-World Go Programming and explore how to use Go in the most practical way I can

in this series the resources are the book itself, go documentation, and any AI model to clarify some things

Why did i choose Go ?

I chose Go because it provides some kind of balance between simplicity, performance, and practicality. coming from languages like Python, I wanted something that could handle real-world projects without unnecessary complexity. Go’s clean syntax, fast compilation, built-in concurrency, and strong standard library make it ideal for building efficient, reliable software.

so Lets Jump into it

Literals in Go

generally the literal is a notation that represents fixed value in the source code

in this break we will start with the basic literals and will get to the composite literals in the next break

Integer literal

sequence of numbers could be decimal (base 10), binary (base2), octal (base 8), hexadecimal (base 16)

  • Go allows using underscores in numbers without affecting them for better readability so 112_234_124_ is exactly 112234124 but easier to read

  • zero value for integers is 0

Floating-point literal

decimal point that indicates fractional portion of the value
the zero value is 0.0

Rune literal

unlike other programming languages single quotes and double quotes are not interchangeable, single quotes hold runes not strings

Rune represents a single Unicode code point enclosed in single quotes and can be simple characters, escape sequences like \n \t or numeric escapes (valid but not recommended).

the zero value is 0

String literal

could be represented using

  1. interpreted string using double quotes ““ → and they can hold strings or runes inside them but you have to escape backslash, unescaped newline, unescaped double quotes

  2. raw string using backticks `` → you can include any character except backticks which allows you to use quotes and new lines without escaping

the zero value is ““ (empty quotes)

Boolean literal

holds either true of false and its zero value is false

and there is also the Complex literal but it’s not used that much and they actually thought about removing it

Numeric Types

there is 12 numeric types in Go

starting with integer types

and there is also special integer types

  1. byte is uint8

  2. int is int32 for 32-bit CPUs and int64 for 64-bit CPUs so it is compile-time error to compare or perform math between int and int32 or int64 without explicit type conversion

  3. uint follows same rule as int but unsigned

  4. rune which is int32

  5. uintptr which we will get to later in pointers

When to use what ?

how to decide which type to use ? follow this rules

  1. binary file format or network protocol that has an integer or specific size or sign use its corresponding integer type

  2. use generic type parameter to represent integer type in functions

  3. in all other cases just use int

Integer Operators

Go supports +, -, *, /, % (for modulus)

combine arithmetic operators with = to modify value +=, -=, /=, *=, %=

compare using ==, !=, >, >=, <, <=

shift or right left using >>, <<

logic operators AND &, OR |, XOR ^, AND NOT&^

b := ^a //not operation
c := a ^ b //xor operation

also modify values by adding = &=, |=, ^=, &^=, <<=, and >>=

Floating-point types

there is float32 and float64

Dividing nonzero floating variable by 0 returns either +inf or -inf based on the sign

dividing floating variable set to 0 by 0 returns NaN

should we use float number at all ?

in many cases the answer is no because they can’t store the exact number so they store the nearest approximation so it makes some operations harder like equality for example where two numbers might not be equal when you think they are

so in the situations where inexact values are acceptable, otherwise don’t use them

Complex types

var num = complex(12, 24)

zero value is 0+0i

String type

strings are compared for equality using == and inequality using != ordering using >, >=, <, <= and concatenated using +

strings are immutable but we can reassign value of string variable

x := "first value" 
x = "second value"

the value of x will be second value so we changed the memory location by creating a new pointer to second value and the first value will be dealt with by garbage collector

Type Conversion

there is no implicit conversion in Go and we have to do explicit conversion for different types

package main
import (
    "fmt"
)

func main(){
    var x int = 10
    var y float64 = 30.2
    var sum1 float64 = y + float64(x)
    var sum2 int = x + int(y) 
    fmt.Println(sum1, sum2)
}

that’s how to do type conversion but there is some notes

  1. assigning value bigger than its size will cause an overflow

  2. if the value exceeds the size by an operation it will wrap around its maximum value (if the type is integer)

    1. if the type is float it will return either +Inf or -Inf
  3. storing float64 number in float32 loses precision if the value within float32 range but holds precision more than float32 can hold

you can’t use nonzero numbers or nonempty strings as boolean true

in python we could do

//python code
x = 'hello' 
if x: 
    print('not empty')

//go
var x string = "hello"
if x { //this isn't valid
    fmt.Println("not empty")
}

var versus :=

to declare a variable there is more than way

verbose way is to do var name string = “jimmy”

  • if the type is expected from the value we can leave it off var x = 10

  • if you need to assign zero value to type drop = var x int so x = 0

  • you can declare multiple values var x, y int= 10, 20

  • you can declare multiple zeros var x, y int

  • declare multiple types var x,y = 10, "hello"

if we are declaring multiple variables at once we can use declaration list

var (
    x int
    y = 20
    z int = 30
    d, e = 40, "hello"
    f, g string
)

on function level we can do x := 10 and the type inference will identify x as integer

var x = 10
x := 10

var x, y = 10, "hello"
x, y := 10, "hello"

x := 10
x, y := 30, "hello"

the := has only one limitation when declaring variable on package level we have to use var method

the Idiomatic approach

  1. if you are declaring variable with its zero value use var int x

  2. when you are assigning an untyped constant or literal to a variable and the default type for the constant or literal isn't the type you want for the variable use verbose form

    • we can use x := byte(20) but it is more idiomatic to do var x byte = 20
  3. := is used to assign to new and existing variables (known as shadowing and we will get to it later)

    • so it is better to declare new variables with var and do assignment for new and old using = operator

the validity of declaring multiple variables at once doesn’t necessarily mean you should do it so it is better to do it only if multiple values are returned from function or with comma ok idiom value, err := expression like opening a file or so

Constants

you can declare a constant value using const name type = value

and it can hold numeric, boolean, strings, runes, values returned by built-in functions, or expressions that consists of operators and preceding values like const x = 10 + 13

const y = 10
const z = 12
const x = z + y //compiles 22

a := 10
b := 12
const c = a+b //won't compile

Constants in GO aren't stored in memory like normal variables
instead the compiler does what is known as constant inlining where it replaces the x constant for example with the value 10 directly in the generated code

so trying something like this will cause error

const x int8 = 10
fmt.Println(&x) //unaddressableoperand error

are Constants typed or untyped ?

const x = 10
var y int = x //x is int here 
var z float64 = x // x is assigned as float here 
var d byte = x //x is assigned as byte here

and the typed constant would look like this const typedx int = 10 and this works only for constants but not normal variables

the variables always have a certain type at compile time

Constants may be untyped; variables never are

Unused variables

One of the Go requirements is that every declared local variable must be read and it causes compile-time error if you declare this variable and don't read its value

this happens in function (local) level only but on package level you can create variables and don't read them

this doesn't affect constants cause as we said the constants are calculated at compile time and they either used and written in the generated coded or not used and discarded

Naming Variables

identifiers must start with letter or underscore and contain numbers, underscores, and letters

letters in go isn’t just A-Za-z but any character with Unicode letter considered letter

all the next identifiers are valid

var café = 1
var عدد = 5
var π = 3.14
var 数据 = 42
var _0 = 0
var __ = "double underscore"

Idiomatic naming convention

  • use short variable names within functions or small blocks like

    • i, j in loops and k,v for key and value
  • in package-level variables or constants use more descriptive long names

  • for non-exported functions or variables use camelCase

  • for exported variable functions or variables use PascalCase

  • PascalCase for Types (structs, interfaces, slices, etc.)

Exercises

Exercise 1

package main
import "fmt"

func main() {
    var i = 20
    var f = float64(i)
    fmt.Println(i, f)
}

Exercise 2

package main
import "fmt"

func main() {
    const value = 0
    i := value
    var f float64 = value
    fmt.Println(i, f)
}

Exercise 3

this is one way of calculating the max value of variable

when we do var smallI = int32(0) this will store 32 zero in the smallI variable so to calculate the max value we need to revert each bit to 1 so it gets the maximum value

package main

import (
    "fmt"
    "math"
)
func main() {
    var b = ^byte(0)
    var smallI = ^int32(0)
    var bigI = ^uint64(0)
    b += 1
    smallI += 1
    bigI += 1
    fmt.Println(b, smallI, bigI)
}

Takes

So far, Go doesn’t feel very different from Python at the surface level, the differences are mostly syntactic

the only differences I’ve seen so far

  • the implicit conversion

  • constants aren’t stored in memory but used in the generated code if they are used

  • naming conventions

so stick around for next break where we will break more stuff

feel free to reach out to me / X

Peace Out GIFs | Tenor

Breaking Things with Go

Part 10 of 10

This series is my learning log while studying Go. I share progress, mistakes, notes, and opinions as I explore the language by breaking things, fixing them, and understanding how Go really works.

Start from the beginning

10th Break: Functions in GO

anonymous functions, closures, functions as parameters, defer