Share & grow the world's code base!

Delve into a community where programmers unite to discover code snippets, exchange skills, and enhance their programming proficiency. With abundant resources and a supportive community, you'll find everything essential for your growth and success.

29 snippets
  • Detect OS in Go

    package main
    
    import (
        "fmt"
        "runtime"
    )
    
    func main() {
        // The runtime.GOOS constant can be used to detect the OS at runtime,
        // since this constant is only set at runtime.
        os := runtime.GOOS
    
        switch os {
        case "windows":
            fmt.Println("Windows")
        case "darwin":
            fmt.Println("MacOS")
        case "linux":
            fmt.Println("Linux")
        default:
            fmt.Printf("%s.\n", os)
        }
    
        // The runtime.GOARCH constant can be used to determine the target architecture of a running program.
        fmt.Println(runtime.GOARCH)
    }
    
    // Output:
    // Linux
    // amd64

    GOOS constant to determine the operating system your Go program is running on. Here's an example of how to check the operating system in Go.

  • Create temporary file or directory in Go

    package main
    
    import (
        "fmt"
        "os"
        "path/filepath"
    )
    
    func checkErr(err error) {
        if err != nil {
            panic(err)
        }
    }
    
    func main() {
        // The simplest way to create a temporary file is to call os.CreateTemp.
        // It will create and open the file for reading and writing.
        // We used "" as the first argument, so os.CreateTemp will create a file in the default directory.
        tmpFile, err := os.CreateTemp("", "tmpfile")
        checkErr(err)
        defer os.Remove(tmpFile.Name())
    
        fmt.Println("Temp file name:", tmpFile.Name())
    
        // Write some data to the temporary file
        _, err = tmpFile.Write([]byte{1, 2, 3, 4, 5})
        checkErr(err)
    
        // If we intend to write a lot of temporary files, we may prefer to create a temporary directory.
        // The arguments to os.MkdirTemp are the same as for os.CreateTemp, but it returns the directory name rather than the opened file.
        dName, err := os.MkdirTemp("", "tmpdir")
        checkErr(err)
        defer os.RemoveAll(dName)
        
        fmt.Println("Temp directory name:", dName)
    
        fName := filepath.Join(dName, "testFile")
        err = os.WriteFile(fName, []byte{1, 2, 3, 4, 5}, 0666)
        checkErr(err)
        defer os.Remove(fName)
    }
    
    // Output:
    // Temp file name: /tmp/tmpfile3400905374
    // Temp directory name: /tmp/tmpdir2812568099

    During program execution, we often want to create data that is not needed after the program exits. Temporary files and directories are useful for this purpose because they do not pollute the file system over time.

  • Panic recovery in Go

    package main
    
    import "fmt"
    
    func main() {
        // Recover function must be called inside a deferred function.
        // When the enclosing function panics, defer is activated and the restore call inside it catches the panic.
        defer func() {
            if r := recover(); r != nil {
                fmt.Printf("recovered: %s\n", r)
            }
        }()
    
        panic("some fatal error")
        
        // This code won't run because of panic.
        // Basic operations stop during a panic and resume during a deferred close.
        fmt.Println("after panic")
    }

    Go allows you to recover from a panic with a built-in recover function. Recovery can prevent a panic from causing the program to abort and instead allow it to continue executing.

  • Writing JSON to a file in Python

    import json
    import os
    import uuid
    
    filename = str(uuid.uuid4()) # create random file name
    
    # JSON data to be written
    jsonDict ={
        "firstname" : "John",
        "lastname" : "Doe",
        "age" : 30,
        "phonenumber" : "9976770500"
    }
    
    # write JSON to file
    with open(filename, "w") as f:
        json.dump(jsonDict, f)
    
    # read JSON string from file
    f = open(filename, "r")
    print(f.read())
    f.close()
    os.remove(filename)
    
    # Output:
    # {"firstname": "John", "lastname": "Doe", "age": 30, "phonenumber": "9976770500"}

    You can write JSON to a file using the json.dump() function from the JSON module combined with file handling in Python. In thisexample, we open a file in writing mode. If the file doesn't exist, it will be created. The json.dump() function converts the Python dictionary into a JSON string, which is then saved in the file.

  • Read JSON file using Python

    import json
    import uuid
     
    jsonString = '{"firstname": "John", "lastname": "Doe"}'
    
    # Create random file name and write json to file
    filename = str(uuid.uuid4())
    
    with open(filename, "w") as f:
        f.write(jsonString)
    
    # Parse JSON string
    # Deserializes json string into dict
    print("Parse JSON string")
    jsonDict = json.loads(jsonString)
    
    # Iterating through the json
    for key, value in jsonDict.items():
        print(key, value)
    
    print()
    #----------------------------------------------------#
    
    print("Read JSON file")
    f = open (filename, "r")
     
    # Reading from file
    jsonDict = json.loads(f.read())
     
    # Iterating through the json
    for key, value in jsonDict.items():
        print(key, value)
     
    # Closing file
    f.close()
    
    # Output
    # Parse JSON string
    # firstname John
    # lastname Doe
    #
    # Read JSON file
    # firstname John
    # lastname Doe

    This exampleillustrates how to read from both a string and a JSON file. Initially, we have a JSON string stored in the variable 'jsonString'. We convert this JSON string into a Python dictionary using json.loads() method, which is then stored in the variable 'jsonDict'. Next, we read a JSON string stored in a file using json.loads(). To achieve this, we first convert the JSON file into a string using file handling, similar to the previous example. Then, we convert it into a string using the read() function. The subsequent steps mirror those followed earlier, utilizing the json.loads() method.

  • Read a file line by line in Python

    import os
    import uuid
    
    filename = str(uuid.uuid4()) # create random file name
    wLines = ["First line\n", "Second line\n", "Third line\n"]
    
    # writing lines to file
    f = open(filename, 'w')
    f.writelines(wLines)
    f.close()
    
    #--------------------------------------------------------#
    
    print("-----Read lines using 'readlines' method-----")
    f = open(filename, 'r')
    rLines = f.readlines()
    
    for lineNumber, line in enumerate(rLines, 1):
    	print("Line {}: {}".format(lineNumber, line.strip()))
    
    #--------------------------------------------------------#
    
    print("-----Read lines using 'readline' method-----")
    f = open(filename, 'r')
    lineNumber = 1
     
    while True:
        lineNumber += 1
     
        # Get next line from file
        line = f.readline()
     
        # if line is empty
        # end of file is reached
        if not line:
            break
        print("Line {}: {}".format(lineNumber, line.strip()))
     
    f.close()
    
    #--------------------------------------------------------#
    
    print("-----Read lines via file object iteration-----")
    f = open(filename, 'r')
    
    for lineNumber, line in enumerate(f, 1):
        print("Line {}: {}".format(lineNumber, line.strip()))
    
    #--------------------------------------------------------#
    
    print("-----Read lines via file contex manager-----")
    with open(filename, "r") as f:
        for lineNumber, line in enumerate(f, 1):
            print("Line {}: {}".format(lineNumber, line.strip()))
    
    os.remove(filename) # remove file
    
    # Output example:
    
    # Read lines using 'readlines' method
    # Line 1: First line
    # Line 2: Second line
    # Line 3: Third line

    Here's an example of reading from a file line by line in Python.

  • Context manager in Python

    # File management using context manager
    class FileManager():
        def __init__(self, filename, mode):
            self.filename = filename
            self.mode = mode
            self.file = None
      
        # The __enter__ method opens the file and returns a file object
        def __enter__(self):
            print('Open file: {}'.format(self.filename))
            self.file = open(self.filename, self.mode)
            return self.file
    
        # The __exit__ method takes care of closing the file on exiting the with block 
        def __exit__(self, etype, value, traceback):
            print('Close file: {}'.format(self.filename))
            self.file.close()
    
    # A FileManager object is created with test.txt as the filename and "write" mode
    # when __init__ method is executed
    with FileManager('test.txt', 'w') as f:
        f.write('First line\n')
        f.write('Second line\n')
    
    # The file is already closed thanks to the automatic call to the __exit__ method
    print('File closed: {}\n'.format(f.closed))
    
    with FileManager('test.txt', 'r') as f:
        for line in f:
            print(line.rstrip())
    
    # Output
    #Open file: test.txt
    #Close file: test.txt
    #File closed: True
    #
    #Open file: test.txt
    #First line
    #Second line
    #Close file: test.txt

    When creating context managers using classes, be sure to ensure that the class includes methods: __enter__() and __exit__(). The __enter__() method provides a resource to be managed, and __exit__() performs cleanup operations without returning any value. To understand the basic structure of building context managers using classes, let's look at a simple FileManager class for managing files.

  • Writing files in Go

    package main
    
    import (
        "bufio"
        "fmt"
        "os"
    )
    
    func checkErr(err error) {
        if err != nil {
            panic(err)
        }
    }
    
    func main() {
        content := "Some content"
        // write a string (or just bytes) into a file
        err := os.WriteFile("/tmp/dfile1", []byte(content), 0644)
        checkErr(err)
    
        // open a file for writing
        file, err := os.Create("/tmp/dfile2")
        checkErr(err)
        // defer a Close immediately after opening a file
        defer file.Close()
    
        bytesCount, err := file.Write([]byte(content))
        checkErr(err)
        fmt.Printf("wrote %d bytes\n", bytesCount)
    
        bytesCount, err = file.WriteString("Some other content\n")
        checkErr(err)
        fmt.Printf("wrote %d bytes\n", bytesCount)
        // flush writes to a stable storage (file system for example)
        file.Sync()
    
        // bufio provides buffered writers
        writer := bufio.NewWriter(file)
        bytesCount, err = writer.WriteString("Some othe buffered content\n")
        checkErr(err)
        fmt.Printf("wrote %d bytes\n", bytesCount)
        // ensure all buffered operations have been applied to the underlying writer
        writer.Flush()
    }

    Here are examples of writing data to files using Go.

  • Generate random hash or token in Go

    package main
    
    import (
    	"crypto/rand"
    	"crypto/sha256"
    	"encoding/hex"
    	"fmt"
    )
    
    func GenerateRandomHash(n int) (string, error) {
    	b := make([]byte, n)
    	_, err := rand.Read(b)
    
    	// Note that err == nil only if we read len(b) bytes.
    	if err != nil {
    		return "", err
    	}
    
    	hasher := sha256.New()
    	hasher.Write(b)
    	sha := hex.EncodeToString(hasher.Sum(nil))
    
    	return sha, nil
    }
    
    func main() {
    	hash, err := GenerateRandomHash(512)
    
    	if err != nil {
    		panic(err)
    	}
    
    	fmt.Println(hash)
    }
    
    // go run main.go 
    // 34c0fb393623843e56719b5d9d66385a55b4b4d3393187b7b1a76aee46c421c5

    Here is an example of randomly generating a hash or token in Go.

  • SHA256 hashes in Go

    package main
    
    import (
        "crypto/sha256"
        "fmt"
    )
    
    func main() {
        str := "some string to calculate hash"
        hash := sha256.New()
    
        hash.Write([]byte(str))
        sum := hash.Sum(nil) // the argument can be used to append to an existing byte slice
    
        fmt.Println(str)
        fmt.Printf("%x\n", sum)
    }
    
    // go run main.go 
    // some string to calculate hash
    // 7aad383b9ad516fa67057adc283ce2cf71858aff317a5e267adebfdbd5dda5fd

    SHA256 hashes are commonly used to generate short identifiers for binary or text data. This example shows how to calculate SHA256 hashes for string in Go.

  • Example of using mutexes in Go

    package main
    
    import (
    	"fmt"
    	"sync"
    )
    
    // without using mutex the following error can happen: "fatal error: concurrent map writes" while changing the map in multiple goroutines
    type Storage struct {
    	sync.Mutex
    	storage map[string]int // map is not threade-safe
    }
    
    func (s *Storage) Increment(name string) {
    	s.Lock() // lock the mutex before accessing counters
    	defer s.Unlock() // unlock the mutex at the end of the function using a defer statement
        s.storage[name]++
    }
    
    func (s *Storage) Decrement(name string) {
    	s.Lock()
        defer s.Unlock()
    	s.storage[name]--
    }
    
    func main() {
    	s := &Storage{
    		storage: make(map[string]int),
    	}
    
    	wg := sync.WaitGroup{}
    	wg.Add(5)
    
        // increment a named counter in a loop
    	increment := func(name string, count uint) {
    		for i := 0; i < int(count); i++ {
    			s.Increment(name)
    		}
    
    		wg.Done()
    	}
    
        // decrement a named counter in a loop
    	decrement := func(name string, count uint) {
    		for i := 0; i < int(count); i++ {
    			s.Decrement(name)
    		}
    
    		wg.Done()
    	}
    
        // run 5 goroutines concurrently
    	go increment("a", 1000)
    	go decrement("a", 500)
    
    	go increment("b", 1000)
    	go increment("b", 1000)
    	go decrement("b", 1500)
    
    	wg.Wait() // wait for the goroutines to finish
    
    	fmt.Println(s.storage)
    }
    
    // $ go run main.go  
    // map[a:500 b:500]
    
    // without mutex the following error can happen
    // $ go run main.go
    // fatal error: concurrent map writes

    Mutexes can be used to safely access data across multiple goroutines.This example shows how to use mutexes in Go to change a map concurrently and safely.

  • Handle OS signals in Go

    package main
    
    import (
        "fmt"
        "os"
        "os/signal"
        "syscall"
    )
    
    func main() {
        sigs := make(chan os.Signal, 1) // create channel for signal, it should be buffered
        signal.Notify(sigs, syscall.SIGINT) // register the channel to receive notifications of the specified signals
        done := make(chan bool, 1)
    
        go func() {
            sig := <-sigs // wait for OS signal, once received, notify main go routine
            fmt.Printf("\nos signal: %v\n", sig)
            done <- true
        }()
    
        fmt.Println("awaiting signal")
        <-done // wait for the expected signal and then exit
        fmt.Println("exiting")
    }
    
    // $ go run main.go 
    // awaiting os signal
    // ^C
    // os signal: interrupt
    // exiting program

    Here is an example go program for processing Unix signals using channels. Signal processing can be useful, for example, for correct terminating of program when receiving SIGTINT.

  • How Select on Channel Works in Golang

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func main() {
        // in this example we will choose between two channels
        c1 := make(chan string)
        c2 := make(chan string)
    
        go func() {
            time.Sleep(1 * time.Second)
            c1 <- "one"
        }()
    
        // each channel will receive a value after some time
        go func() {
            time.Sleep(2 * time.Second)
            c2 <- "two"
        }()
    
        // use select statement to wait for both values ​​at the same time,
        // printing each one as it arrives
        for i := 0; i < 2; i++ {
            select {
            case msg1 := <-c1:
                fmt.Println("received", msg1)
            case msg2 := <-c2:
                fmt.Println("received", msg2)
            }
        }
    }

    Select statement allows you to wait for multiple operations on a channel.

  • Worker pools in Go

    package main
    
    import (
        "fmt"
        "time"
    )
    
    // this is a worker that we will run in several parallel instances
    // these workers will receive tasks through the 'jobs' channel and send the results to 'results'
    // we will wait for one second for each task to simulate heavy requests
    func worker(id int, jobs <-chan int, results chan<- int) {
        for j := range jobs {
            fmt.Println("worker", id, "started job", j)
            time.Sleep(time.Second)
            fmt.Println("worker", id, "finished job", j)
            results <- j * 2
        }
    }
    
    func main() {
        // to use worker pool, we need to send a task and receive the execution results
        // therefore 2 channels are created
        jobs := make(chan int, 100)
        results := make(chan int, 100)
    
        // start 3 workers, initially blocked because no assignments yet
        for w := 1; w <= 3; w++ {
            go worker(w, jobs, results)
        }
    
        // send 5 jobs and then close the channel, notofying that all jobs have been sent
        for j := 1; j <= 5; j++ {
            jobs <- j
        }
    
        close(jobs)
    
        // collect all the results
        // this also ensures that the goroutines have ended
        for a := 1; a <= 5; a++ {
            <-results
        }
    }

    This example shows how to implement a worker pool using channels and goroutines.

  • Channel synchronization in Go

    package main
    
    import (
        "fmt"
        "time"
    )
    
    // the channel is used to notify main goroutine that the function completed successfully
    func worker(done chan bool) {
        fmt.Println("working...")
        time.Sleep(time.Second)
        fmt.Println("done")
    
        done <- true // send a value to indicate that the function completed successfully
    }
    
    func main() {
        done := make(chan bool, 1) // create a buffered channel for notification
        go worker(done) // run worker
    
        <-done // blocked until a notification is received from the worker from the channel
               // if you remove the line <- done the program will close before the worker starts
    }

    Channels can be used to synchronize execution between goroutines. Here is an example of using a channel to wait for a goroutine to complete.

  • Binary search algorithm in PHP

    <?php 
      
    function binarySearch(array $arr, int $target): int 
    { 
        $low = 0; 
        $high = count($arr) - 1; 
          
        while ($low <= $high) {          
            // compute middle index 
            $mid = floor(($low + $high) / 2);  
      
            if ($arr[$mid] > $target) { 
                // search the left side of the array 
                $high = $mid -1; 
            } else if ($arr[$mid] < $target) { 
                // search the right side of the array 
                $low = $mid + 1; 
            } else {
                // element found at mid 
                return $mid; 
            }
        } 
          
        // If we reach here element x doesnt exist 
        return -1; 
    } 
      
    // Driver code 
    $arr = [1, 2, 3, 4, 5]; 
    $target = 3;
    $result = binarySearch($arr, $target);
    
    if($result !== -1) { 
        echo "Target '$target' exists at position $result"; 
    } else {
        echo "Target '$target' does not exist";
    }

    Double search is a search method used to find an element in a sorted array.

  • Binary search algorithm in Python

    # Returns index of target in arr if present, else -1
    def binary_search(arr, target):
    	low = 0
    	high = len(arr) - 1
    
    	while low <= high:
    		# Check base case
    		mid = (high + low) // 2
    
    		# If element is smaller than mid, then it can only
    		# be present in left subarray
    		if arr[mid] > target:
    			high = mid - 1
    		# Else the element can only be present in right subarray
    		elif arr[mid] < target:
    			low = mid + 1
    		# If element is present at the middle itself
    		else:
    			return mid
    
    	# Element is not present in the array
    	return -1
    
    # Test array
    arr = [ 2, 3, 4, 10, 40 ]
    target = 10
    
    result = binary_search(arr, target)
    
    if result != -1:
    	print("Element is present at index", str(result))
    else:
    	print("Element is not present in array")

    Binary Search is a searching algorithm for finding an element's position in a sorted array. In this approach, the element is always searched in the middle of a portion of an array.

  • Binary search algorithm in Go

    package main
    
    import "fmt"
    
    // return target index if it exists in arr
    func search(arr []int, target int) int {
        low := 0
        high := len(arr) - 1
    
        for low <= high {
            mid := (low + high) / 2
    
            if arr[mid] < target {
                low = mid + 1
            } else if arr[mid] > target {
                high = mid - 1
            } else {
                return mid
            }
        }
    
        return -1
    }
    
    func main() {
        target := 7
        items := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
        fmt.Printf("Element '%d' index is %d", target, search(items, target))
    }
    
    // $ output
    // 6

    The binary search algorithm employs a divide-and-conquer approach to locate an item within a sorted array or list. It begins by comparing the target value to the middle element of the array. If they are not identical, the algorithm eliminates the half of the array where the target cannot reside and proceeds the search on the remaining half. This process iterates, with each step narrowing down the search range until the target value is discovered. If the search concludes with an empty remaining half, it indicates that the target is not present in the array.

  • Example of WaitGroup in Go

    package main
    
    import (
    	"fmt"
    	"sync"
    	"time"
    )
    
    func main() {
    	wg := &sync.WaitGroup{} // WaitGroup is used to wait for the execution of all running goroutines
    
    	for i := 1; i <= 5; i++ {
    		wg.Add(1) // launch several goroutines and increment the counter in WaitGroup for each running goroutine
    
    		go func(id int) {
    			worker(id, wg)
    		}(i)
    	}
    
    	fmt.Println("waiting for all goroutines to complete")
    	wg.Wait() // block the execution of the program until the WaitGroup counter becomes equal to 0 again
    	fmt.Println("done")
    }
    
    func worker(id int, wg *sync.WaitGroup) {
    	fmt.Printf("worker %d started\n", id)
    	time.Sleep(time.Second) // Sleep simulates a long task
    	
        fmt.Printf("worker %d finished\n", id)
    	wg.Done() // notify WaitGroup that the worker has completed
    }
    
    // $ go run waitgroups.go 
    // waiting for all goroutines finished
    // worker 4 started
    // worker 1 started
    // worker 2 started
    // worker 3 started
    // worker 2 finished
    // worker 4 finished
    // worker 1 finished
    // worker 3 finished
    // done

    To wait for multiple goroutines to execute, you can use the built-in WaitGroup construct.

  • Atomic counters in Go

    package main
    
    import (
    	"fmt"
    	"sync"
    	"sync/atomic"
    )
    
    func main() {
    	var atomicCounter, nonAtomicCounter uint64
    	wg := sync.WaitGroup{}
    
    	for i := 0; i < 50; i++ {
    		wg.Add(1)
    
    		go func() { // run 50 goroutines, each goroutine increases the counter 1000 times
    			for c := 0; c < 1000; c++ {
    				atomic.AddUint64(&atomicCounter, 1) // increase atomic counter
    				nonAtomicCounter++ // increase non-atomic counter
    			}
    
    			wg.Done()
    		}()
    	}
    
    	wg.Wait() // wait until all goroutines finish
    	
    	fmt.Println("atomic counter value:", atomicCounter)
    	fmt.Println("non atomic counter value:", nonAtomicCounter)
    }
    
    // go run counters.go 
    // atomic counter value: 50000
    // non atomic counter value: 30648

    An example of using the sync/atomic package for atomic counters accessed by goroutines.