Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      Sunshine And March Vibes (2025 Wallpapers Edition)

      May 16, 2025

      The Case For Minimal WordPress Setups: A Contrarian View On Theme Frameworks

      May 16, 2025

      How To Fix Largest Contentful Paint Issues With Subpart Analysis

      May 16, 2025

      How To Prevent WordPress SQL Injection Attacks

      May 16, 2025

      Microsoft has closed its “Experience Center” store in Sydney, Australia — as it ramps up a continued digital growth campaign

      May 16, 2025

      Bing Search APIs to be “decommissioned completely” as Microsoft urges developers to use its Azure agentic AI alternative

      May 16, 2025

      Microsoft might kill the Surface Laptop Studio as production is quietly halted

      May 16, 2025

      Minecraft licensing robbed us of this controversial NFL schedule release video

      May 16, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      The power of generators

      May 16, 2025
      Recent

      The power of generators

      May 16, 2025

      Simplify Factory Associations with Laravel’s UseFactory Attribute

      May 16, 2025

      This Week in Laravel: React Native, PhpStorm Junie, and more

      May 16, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      Microsoft has closed its “Experience Center” store in Sydney, Australia — as it ramps up a continued digital growth campaign

      May 16, 2025
      Recent

      Microsoft has closed its “Experience Center” store in Sydney, Australia — as it ramps up a continued digital growth campaign

      May 16, 2025

      Bing Search APIs to be “decommissioned completely” as Microsoft urges developers to use its Azure agentic AI alternative

      May 16, 2025

      Microsoft might kill the Surface Laptop Studio as production is quietly halted

      May 16, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»Key Golang Concepts You Should Learn as a Beginner Go Developer

    Key Golang Concepts You Should Learn as a Beginner Go Developer

    November 12, 2024

    Learning new programming concepts can be hard. So you’ll need a guide or a roadmap to help you navigate through the process.

    Learning Golang is no exception. And as a beginner, you’ll need to work diligently to learn the fundamental building blocks of the language. These key introductory concepts are important as they help you lay the groundwork for more complex development.

    In this article, we will explore the main parts of Go that every beginner should learn to build a strong foundation in the language. So if you’re just starting out, this guide will help you solidify your knowledge and start building projects that’ll make you more confident coding in Golang.

    Table of Contents

    • Variables and Datatypes

    • Control Structures

      • 1. If/Else Statements

      • 2. Switch Statements

      • 3. For Loops

    • Functions

    • Pointers

    • Error Handling

    • Goroutines and Concurrency

    • Structs and Inheritance

    • Go Standard Library

      • Accessing and Using a Package from the Standard Library
    • Testing in Go

    • That’s a Wrap!

    Variables and Datatypes

    Variables in Go are used to store and manage data within a program. They act as containers that hold values of specific types. Variables allow you to retrieve and manipulate stored information.

    Below is an example of using variables in Go:

    package main
    
    import "fmt"
    
    func main(){
     // Variables
        var age int = 30
        var name string = "John"
        salary := 50000.50 // Short variable declaration(only to be used inside a function
      fmt.Println(age)
      fmt.Println(name)
       fmt.Println(salary)
    }
    

    To learn more about variables, you can check out my tutorial on them here.

    On the other hand, data types define the kind of data a variable can hold. Since Go is a statically typed language, it requires you to specify the data type of each variable.

    Some of the main data types in Go include:

    • Boolean: Represents a true or false value. It’s used for logical decisions in the program.

    • Number: Includes integer types (like int, int32, int64) and floating-point types (like float32, float64) to store whole numbers and decimal values.

    • String: Represents a sequence of characters (text). It’s used to store words, phrases, or any text-based data.

    • Array: A collection of fixed-size elements of the same type. Arrays allow you to store multiple values in a single variable.

    • Slice: Similar to arrays, but with a dynamic size. Slices are more commonly used in Go since they offer greater flexibility.

    • Map: A collection of key-value pairs. Maps are used when you want to associate values with specific keys for fast lookup.

    • Struct: A way to group related data together. Structs allow you to define custom data types with multiple fields, each of a different type.

    • Pointer: Holds the memory address of another variable, allowing for more efficient memory manipulation in certain cases.

    Below is an example showing how some of these data types work:

    package main
    
    import "fmt"
    
    func main() {
    
        // Data Types
        var isEmployed bool = true // boolean
        var count int = 42 // integer
        var greeting string = "Hello, Go!" // string
    
        // Struct
        type Rectangle struct {
            width  float64
            height float64
        }
        rect := Rectangle{width: 10.5, height: 5.2}
    
        fmt.Println("Is Employed:", isEmployed)
        fmt.Println("Count:", count)
        fmt.Println("Greeting:", greeting)
        fmt.Println("Numbers:", numbers)
        fmt.Printf("Rectangle: width = %.2f, height = %.2fn", rect.width, rect.height)
    
    }
    

    In this example, we demonstrate the usage of several data types:

    1. bool: The isEmployed variable is declared as a bool and assigned the value true.

    2. int: The count variable is declared as an int and assigned the value 42.

    3. string: The greeting variable is declared as a string and assigned the value "Hello, Go!".

    4. struct: We define a new data type called Rectangle that has two fields: width and height, both of which are float64. We then create a new instance of Rectangle and assign values to its fields.

    Variables and data types form the basis of programming in Go. These concepts are essential building blocks that you’ll use in almost every program you write. They allow you to store, manipulate, and organize data effectively.

    With a strong command of variables and data types, you’ll also be better equipped to tackle more advanced Go concepts and write robust, efficient code as you progress in your learning journey.

    Control Structures

    In Go, control structures are simply constructs that control the flow of execution in a program. They allow you to perform different actions based on conditions or repeatedly execute a block of code.

    Some of the main control structures in Go include:

    1. If/Else Statements

    The if/else statement in Go executes a block of code based on a condition. If the condition returns true, the code inside the if block is performed. If the condition returns false, the else block (if any) is executed.

    For example:

    package main
    
    import "fmt"
    
    func main() {
        x := 10
        if x > 5 {
            fmt.Println("x is greater than 5")
        } else {
            fmt.Println("x is 5 or less")
        }
    }
    

    In the code above, if x is greater than 5, the first block is executed. Otherwise, the else block runs.

    2. Switch Statements

    The switch statement is a multi-directional branch that allows you to execute different blocks of code depending on the value of an expression. It’s easier to read than multiple if/else statements.

    For example:

    package main
    
    import "fmt"
    
    func main() {
        day := "Monday"
        switch day {
        case "Monday":
            fmt.Println("Start of the week")
        case "Friday":
            fmt.Println("Almost weekend")
        default:
            fmt.Println("It's another day")
        }
    }
    

    In the code above, the output will be “Start of the week” because the day variable matches the Monday case.

    3. For Loops

    Go only has one looping construct, the for loop. It can be used in various forms: traditional loops, range-based loops (to iterate over slices, maps, and so on), and infinite loops.

    Below is an example of a traditional loop:

    package main
    
    import "fmt"
    
    func main() {
        for i := 0; i < 5; i++ {
            fmt.Println(i)
        }
    }
    

    In the code above, the loop prints the numbers 0 through 4.

    The range based loop provides a simplified way for iteration on slices, maps, and others. It makes it easier to access each element directly without needing to manually handle index or length checks. The loop automatically provides both the index and the value during each iteration, improving readability and reducing the chance of off-by-one errors or other indexing issues.

    Below is an example of a range-based loop:

    package main
    
    import "fmt"
    
    func main() {
        nums := []int{1, 2, 3, 4}
        for i, num := range nums {
            fmt.Println(i, num)
        }
    }
    

    In the code above, the for loop is used to iterate over the nums slice. The range keyword returns both the index and the value of each element in the slice. This makes it easy to process all elements of a slice without needing a counter variable.

    Functions

    A function in Go is a block of code that performs a specific task. Functions help you organize code by allowing you to construct reusable code logic, which is easier to maintain and understand.

    Below is an example of a function that adds two numbers:

    package main
    
    import "fmt"
    
    func add(a int, b int) int {
        return a + b
    }
    
    func main() {
        result := add(2, 3)
        fmt.Println("Result:", result)
    }
    

    Here, we have a simple function called add that takes two integer parameters (a and b) and returns their sum, which is also an integer type. The function is then called inside the main function which prints the result.

    Functions are the foundation of Go programs, and understanding their structure and capabilities is critical.

    Pointers

    In Go, a pointer is a variable that stores the memory address of another variable. A pointer “points to” the region in memory where the actual value is stored rather than retaining the value itself.

    Pointers are useful when you need to pass references to large structures or when you want to modify a variable’s value from inside a function. They are also critical for memory management.

    Below is a basic example that illustrates how pointers work in Go:

    package main
    
    import "fmt"
    
    func main() {
        var num int = 10
    
        var ptr *int = &num
    
        fmt.Println("Value of num:", num)      
        fmt.Println("Pointer address:", ptr)   
        fmt.Println("Value at pointer:", *ptr)
    
        *ptr = 20
        fmt.Println("Updated value of num:", num) 
    }
    

    In the example above, we first declare a variable num and assign it the value of 10. We then create a pointer ptr that stores the memory address of num (using &num) and then print it out to see it. To access the stored pointer value, we use the *ptr. We then modify the value of num through the pointer by setting *ptr to 20, which directly changes num to 20.

    This demonstrates how pointers allow you to access and modify variables via their memory addresses, which is useful for more efficient memory handling and function parameter passing in Go.

    To get a better understanding of what pointers are, you can check out my article on them here.

    Error Handling

    In order to write robust and build reliable applications, you’ll need to learn about error handling. Compared to other programming languages, Go takes a unique approach to error handling, encouraging you to handle problems explicitly and immediately rather than relying on exceptions.

    In Go, errors are treated as values, which means they are returned from functions just like any other value and must be handled by the developer. This approach helps to promote clarity and also ensures that potential issues are dealt with at the point where they occur.

    Below is some example code to illustrate basic error handling in Go:

    package main
    
    import (
        "errors"
        "fmt"
    )
    
    func divide(a, b float64) (float64, error) {
        if b == 0 {
            return 0, errors.New("cannot divide by zero")
        }
        return a / b, nil
    }
    
    func main() {
        result, err := divide(10, 0)
        if err != nil {
            fmt.Println("Error:", err)
        } else {
            fmt.Println("Result:", result)
        }
    }
    

    In the code above, we have a divide function that takes two numbers and returns both a result and an error. If the second number is zero, an error is returned because division by zero is not allowed.

    We also have a main function where we call divide and check if an error occurred by examining the err value. If an error is present, we handle it by printing an error message. Otherwise, we print the result.

    This approach to error handling in Go ensures that errors are caught and dealt with right away, making the program more reliable and easier to troubleshoot.

    Goroutines and Concurrency

    Goroutines and concurrency are concepts that let your code efficiently execute multiple tasks in parallel.

    A goroutine is a function that runs concurrently with other functions. Goroutines are incredibly lightweight, with a small memory footprint, allowing you to run thousands (or even millions) of goroutines simultaneously without overwhelming system resources.

    Concurrency, on the other hand, refers to a program’s capacity to handle numerous tasks at the same time. It does not necessarily imply that the tasks are executing concurrently (which is parallelism) but rather that they are making progress independently.

    Let’s look at an example code to illustrate these concepts:

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func printNumbers() {
        for i := 1; i <= 5; i++ {
            fmt.Println(i)
            time.Sleep(1 * time.Second)
        }
    }
    
    func printLetters() {
        for i := 'A'; i <= 'E'; i++ {
            fmt.Printf("%cn", i)
            time.Sleep(1 * time.Second)
        }
    }
    
    func main() {
    
        go printNumbers()  // This runs concurrently
        go printLetters()  // This runs concurrently
    
        // Wait for goroutines to finish
        time.Sleep(6 * time.Second)
        fmt.Println("All tasks completed.")
    }
    

    In the code above, we create two functions, printNumbers and printLetters. One prints numbers from 1 to 5, and the other prints letters from ‘A’ to ‘E’. We launch these functions as goroutines by adding the go keyword before calling them in the main function.

    Goroutines are lightweight threads that allow functions to run concurrently. This means both printNumbers() and printLetters() can execute at the same time without waiting for each other to complete. The key concept here is concurrency, where multiple tasks (like printing numbers and letters) make progress independently, even though they don’t necessarily run in parallel on separate cores.

    In this case, both goroutines sleep for one second between prints, but because they are running concurrently, the numbers and letters can be printed almost simultaneously without blocking each other’s execution.

    To ensure the program doesn’t exit before the goroutines complete their work, we add a time.Sleep(6 * time.Second) in the main function. This gives enough time for both goroutines to finish printing before the program terminates.

    This example illustrates Go’s powerful concurrency model through goroutines, enabling efficient multitasking without the complexity of traditional threading.

    To dive deeper into goroutines and concurrency, Destiny Erhabor did a fine job in explaining what they are in his article here.

    Structs and Inheritance

    In Go, a struct is a composite data type that organizes variables (fields) into a single type. These fields can include a variety of data types, making structs suitable for describing complex data structures. Structs in Go function similarly to classes in other programming languages but without the methods of inheritance.

    Let’s start with an example of a struct:

    type Person struct {
        Name string
        Age  int
    }
    

    In this example, Person is a struct with two fields: Name which is a string and Age which is an int. You can create an instance of this struct like so:

    p := Person{Name: "Alice", Age: 30}
    fmt.Println(p.Name)  // Output: Alice
    

    Go does not have traditional inheritance like some object-oriented languages where one class inherits fields and methods from another. Instead, Go uses composition, which allows you to embed one struct inside another.

    Here’s an example code of struct composition:

    type Employee struct {
        Person
        Position string
    }
    
    e := Employee{
        Person:   Person{Name: "Bob", Age: 25},
        Position: "Developer",
    }
    
    fmt.Println(e.Name)     // Output: Bob
    fmt.Println(e.Position) // Output: Developer
    

    In the code above, the Employee struct embeds the Person struct, and the fields of Person can be accessed directly like e.Name. This mimics some of the behavior you’d expect from inheritance in other languages, but it’s done through composition.

    While Go lacks inheritance, it achieves polymorphism through interfaces. An interface is a type that specifies a set of method signatures. A type is said to implement an interface if it provides the methods declared by that interface.

    What makes Go unique is that it uses implicit implementation, meaning that a type does not need to explicitly declare that it implements an interface – it just has to match the method signatures.

    Let’s see an example:

    type Speaker interface {
        Speak() string
    }
    
    type Person struct {
        Name string
    }
    
    func (p Person) Speak() string {
        return "Hi, my name is " + p.Name
    }
    
    func saySomething(s Speaker) {
        fmt.Println(s.Speak())
    }
    
    func main() {
        p := Person{Name: "Alice"}
        saySomething(p)  // Output: Hi, my name is Alice
    }
    

    In this example, Person implements the Speaker interface by defining a Speak method. The function saySomething takes any type that implements the Speaker interface, demonstrating polymorphism. Go’s interfaces provide a flexible way to design code that is clean and extensible without needing to rely on traditional inheritance.

    Go Standard Library

    It’s important to become familiar with Go’s standard library. It contains a comprehensive collection of packaged libraries that provide you with a wide range of functionalities for tasks like file handling, network communication, string manipulation, data structures, cryptography, testing, and more. This allows you to perform common programming tasks without the need to install external packages.

    Accessing and Using a Package from the Standard Library

    To access a package from the standard library, you simply import it into your Go file using the import statement. Then, you can use the package’s functions directly.

    Some of the packages you can import from the standard library include:

    • fmt for formatted I/O

    • net/http for building web servers

    • io for I/O operations

    • strings for string manipulation

    • time for date and time operations

    For example, let’s look at the fmt package, which is used for formatted input and output. Here’s a basic example of how to use the fmt package to print formatted output:

    package main
    
    import "fmt"
    
    func main() {
        name := "Alice"
        age := 30
        fmt.Printf("Hello, my name is %s and I am %d years old.n", name, age)
    }
    

    In this example:

    • The import "fmt" line allows us to access the fmt package from the standard library.

    • We use fmt.Printf to format and print a string that includes a name (%s for strings) and an age (%d for integers).

    Each package in the standard library is well-documented, with plenty of examples, so it’s a good idea to explore the official Go documentation to better understand how to use these packages in your projects. You can find the documentation for the Go standard library here.

    Testing in Go

    Testing is a first-class citizen in Go. This means that Go treats testing as a core, integral part of the development process.

    Go’s testing framework is built around the testing package, which provides the tools necessary to write tests. You write your tests in separate files, which are automatically detected and executed by the Go tool.

    To write a test, you need to add the suffix _test.go. For example, if your main code file is math, the tests for that file would go into math_test.go.

    Let’s see how to write a simple test. Let’s say we have a simple function in math.go:

    
    package math
    
    func Add(a, b int) int {
        return a + b
    }
    

    To test the Add function, you need to create a test file called math_test.go:

    
    package math
    
    import "testing"
    
    func TestAdd(t *testing.T) {
        result := Add(2, 3)
        expected := 5
        if result != expected {
            t.Errorf("Add(2, 3) = %d; want %d", result, expected)
        }
    }
    

    In the test above:

    • The TestAdd function is defined to test the Add function.

    • The t.Errorf is used to report an error if the result doesn’t match the expected value.

    To run the test, you use this command in your terminal:

    go test
    

    You can also get more verbose output by adding the -v flag like so:

    go test -v
    

    This is just the basics, as there are other types of tests, such as table-driven tests and benchmarking.

    That’s a Wrap!

    In this article, we took a look at nine key concepts to learn as a beginner getting started with Golang.

    And keep in mind that this isn’t everything you’ll need to know when you’re learning Go – these are just what I consider to be the most important basics. And they should help you get your foot in the door of the world of Go.

    If you think I missed a key concept, I’d love it if you’d share it with me so I can update the article. Thank you!

    Source: freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleThis viral iPhone keyboard case is the most ingenious accessory I’ve tested
    Next Article How to Build a Dropbox-like Distributed File Storage System Using MinIO and gRPC

    Related Posts

    Security

    Nmap 7.96 Launches with Lightning-Fast DNS and 612 Scripts

    May 17, 2025
    Common Vulnerabilities and Exposures (CVEs)

    CVE-2025-40906 – MongoDB BSON Serialization BSON::XS Multiple Vulnerabilities

    May 17, 2025
    Leave A Reply Cancel Reply

    Continue Reading

    CVE-2025-4092 – Firefox Memory Corruption Arbitrary Code Execution Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    Doom, Quake, and Turok remaster studio ask what fan-favorite game they should work on next

    News & Updates

    Dashboard Design: Best practices & Design Principles

    Web Development

    CmdCompass – collect, learn, recall terminal commands

    Linux

    Highlights

    CVE-2025-30330 – Adobe Illustrator Heap-based Buffer Overflow Vulnerability

    May 13, 2025

    CVE ID : CVE-2025-30330

    Published : May 13, 2025, 6:15 p.m. | 49 minutes ago

    Description : Illustrator versions 29.3, 28.7.5 and earlier are affected by a Heap-based Buffer Overflow vulnerability that could result in arbitrary code execution in the context of the current user. Exploitation of this issue requires user interaction in that a victim must open a malicious file.

    Severity: 7.8 | HIGH

    Visit the link for more details, such as CVSS details, affected products, timeline, and more…

    Windows 11’s upcoming Continue from Phone could be seamless mobile-desktop integration at its best

    July 2, 2024

    CodeSOD: Mr Number

    January 6, 2025

    cfonts – command line tool for sexy ANSI fonts in the console

    March 19, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.