Concurrency in Go

Table of contents

Go or Golang is an open-source programming language developed at Google by a team of engineers. It was released in 2009 and aims to provide efficient programming, focusing on concurrent operations, garbage collection, and low-level memory access. Go is compiled, statically typed, and has syntax similar to C. Nowadays, it's widely used for developing networked services, web applications, command-line utilities, and more.

Here are some essential features of Go:

  1. Simplicity: Go has a straightforward syntax and minimalistic approach.

  2. Concurrency: The language has built-in concurrency support with Goroutines and channels, making it easy to write concurrent code.

  3. Speed: Go compiles quickly, and its garbage collection makes it much faster than languages like Python.

  4. Standard Library: Go has an extensive standard library that provides several built-in functions for web servers, JSON processing, cryptographic hashing, etc.

  5. Cross-platform support: Go supports cross-compiling to different operating systems, allowing you to run the same code on Windows, macOS, and Linux.

  6. Error handling: Go has a unique error-handling approach using return values, allowing developers to handle errors easily and more efficiently.

  7. Effective memory management: Go uses a Garbage collector (GC) which makes developers write code without worrying about manual memory management.

  8. Built-in documentation: Go has excellent built-in documentation tools and code comments can automatically generate external documentation in HTML format.

  9. Scalability: Go is designed to handle large codebases and backend systems effectively, especially for web applications and servers.

  10. Dependency management: Go has its package manager called go module which allows developers to specify dependencies and version constraints explicitly.

Concurrency in Go

To demonstrate what concurrency is and how it is implemented in golang, here is a piece of code that uploads multiple media files to cloud storage using Goroutines and Channels to achieve concurrency in Golang. To achieve concurrency in golang, we introduce two very important concepts called goroutines and channels.

Goroutines are like lightweight threads that allow us to run a function concurrently with other functions while Channels provide a way for these goroutines to communicate and share data efficiently and safely, without having to use locks or mutexes.

func (server *Server) uploadFile(ctx *gin.Context) {
    response := make(chan *uploader.UploadResult)
    errs := make(chan error)

    form, _ := ctx.MultipartForm()

    for _, file := range form.File["upload[]"] {

        // Open the multipart.File
        fileContent, err := file.Open()
        if err != nil {
            log.Fatal(err)
            continue
        }

        cctx:= ctx.Copy()
        go photoService(cctx, fileContent, uploader.UploadParams{
            PublicID: file.Filename,
            Folder:   "golang_tut"}, response, errs)
    }

    for i := 0; i < len(form.File["upload[]"]); i++ {
        select {
        case resp := <-response:
            fmt.Println(resp.SecureURL)
            ctx.JSON(http.StatusOK, gin.H{"url": resp})

        case err := <-errs:
            log.Println(err)
            ctx.JSON(http.StatusOK, gin.H{"err": err})
        }
    }
}

func photoService(ctx context.Context, file io.Reader, uploader uploader.UploadParams,
    r chan *uploader.UploadResult, e chan error) {

    config, err := util.LoadConfig(".")
    if err != nil {
        log.Fatal(err)
    }

    cld, err := cloudinary.NewFromParams(config.CloudinaryCloudname, config.CloudinaryAPIKEY, config.CloudinarySecret)
    if err != nil {
        e <- err
        return
    }

    resp, err := cld.Upload.Upload(ctx, file, uploader)
    if err != nil {
        e <- err
        return
    }

    r <- resp
}

In summary, achieving concurrency is a vital concept to consider when seeking ways to improve scalability in your systems. Many programming languages lack support for concurrency, and building concurrent functionality often requires writing code with many lines.

However, Go combines the best of both worlds by using the benefits of statically typed languages like C#, C++, and Java, while retaining the simplicity of Python. To achieve concurrency benefits, it only takes a few lines of code.