logo

Go - FAQ

Last Updated: 2024-06-26

Why Go?

  • a simple language with elegant and easy to understand syntax structures
  • fast to build and execute.
  • uses a compile-link model for generating executable binaries from the source code.
  • supports concurrency at the language level. Golang is optimized for concurrency and works well at scale.
  • Automatic garbage collection. more efficient than Java or Python because it executes concurrently alongside the program.
  • more readable than other languages due to a single standard code format.
  • good standard library
  • static type checking.
  • good support for writing unit test

What are packages in Go?

Packages are directories within your Go workspace that contain Go source files or other packages.

  • Every function, variable, and type from your source files are stored in the linked package.
  • Every Go source file belongs to a package, which is declared at the top of the file using: package <packagename>
  • Packages can be imported by import <packagename>

What are differences between packages and modules in Go?

  • a package is a directory of .go files
  • a module is a collection of Go packages, with dependencies and versioning built-in.
    • a module has a file go.mod at its root, it defines the module's import path and its specific dependencies.

With modules:

  • Go projects do not need to reside in GOPATH.
  • Package management is greatly improved.

How to do type conversion in Go?

To convert a number to int: int(a).

How to print type of variable in Go?

Use %T in fmt.Printf()

fmt.Printf("Type: %T\n", a)

How to export an identifier in Go?

  • If the identifier starts with a capital letter, it is exported from the package, and can be accessed by anyone outside the package that declares it it.
  • If the identifier starts with a lowercase letter, it can only be accessed from within the package.

What is a pointer in Go?

A pointer is used to hold the address of a variable.

Which common language features are NOT supported by Go?

Golang doesn't provide support for the following features:

  • class keyword.
  • type inheritance.
  • operator overloading.
  • method overloading.
  • pointer arithmetic.
  • try / catch for error handling
  • generics (only supported after 1.18)

How to define interfaces

Interfaces are a special type in Go that define a set of method signatures but do not provide implementations.

type geometry interface {
    area() float64
    perim() float64
}

What is the empty interface in Go?

Empty interface: an interface type that specifies zero methods.

interface{}

Used to handel values of unknown type.

func foo(v interface{}) {
    // v can be any type.
}

How to handle errors in Go?

Can have multiple checks within the same block, to limit err scope:

if err := Foo(); err != nil {
    // ...
}

Bubble up the errors:

func Bar() error {
    f, err := Foo()
    if err != nil {
        return fmt.Errorf("got error: %w", err)
    }
}

How to concatenate strings?

Use +.

What are function closures?

Function closures is a function value that references variables from outside its body.

What are Lvalue and Rvalue in Golang?

Lvalue

  • Refers to a memory location
  • Represents a variable identifier
  • Mutable
  • May appear on the left or right side of the = operator

Rvalue

  • Represents a data value stored in memory
  • Represents a constant value
  • Always appears on the = operator's right side.

Can you return multiple values from a function?

Yes. For example:

func foo() (string, string) {
   return "a", "b"
}

Swap the values of two variables without a temporary variable

b, a = a, b

What is the easiest way to check if a slice is empty?

len(slice) == 0

String Literals

  • Raw string literals: `raw string`
  • Interpreted string literals: "raw string"

What are the scopes of variables in Go?

Every variable is statically scoped (meaning a variable scope can be identified at compile time) in Go which means that the scope is declared at the time of compilation itself. There are two scopes in Go, they are:

  • Local variables: declared inside a function or a block and is accessible only within these entities.
  • Global variables: declared outside function or block and is accessible by the whole source file.

What is slice in Go?

Slice: variable length sequence for homogeneous data.

An array has a fixed size. A slice, on the other hand, is a dynamically-sized, flexible view into the elements of an array.

Does Go support generics?

Yes, since Go 1.18.

What's the difference between new and make?

  • new: allocates "zeroed" storage for a new item of type T and returns its address, a value of type *T.
  • make: used to initialize slices, maps, and channels; it does not return a pointer.
p := new(chan int)   // p has type: *chan int
c := make(chan int)  // c has type: chan int

What is Type Assertion in Go?

t, isSuccess := i.(T)

It asserts that the interface value i has the concrete type T and assigns the value to the variable t. If the interface value i has T, then t will be assigned; otherwise isSuccess is false and t would have the zero value.

What's the difference between := and =?

  • := (short variable declaration): for declaration + assignment
  • =: for assignment only.

var foo int = 10 is the same as foo := 10.

Note:

  • Go won't let you use := to assign to a variable that has already been declared, unless you are assigning to multiple variables at once, and at least one of those variables is new.
  • := cannot be used outside a function.

What are byte and rune in Go?

  • byte: alias for uint8. Represents ASCII chacaters.
  • rune: alias for int32. Represents a single Unicode character.

How to test code in Go?

  • Go has built-in support for unit testing.
  • Since Go 1.18, fuzzing (a type of vulnerability testing that throws arbitrary data at a piece of software to expose unknown errors and is emerging as a common testing scheme in enterprise development) is integrated into Go's standard toolchain

How is Go different from other programming languages?

  • Go's switch cases need not be constants, and the values involved need not be integers.
  • Unlike C, Go has no pointer arithmetic.
  • Go does not have reference variables.
  • It is not possible to create a Go program where two variables share the same storage location in memory.
  • Interfaces are implemented implicitly. Go interfaces are statically typed duck typing, Java interfaces are alternative to multiple inheritance.

How does inheritance work in Go?

There's no inheritance (e.g. extends and override) in Go, composition is preferred over inheritance; type embedding is the way to implement composition.

How to clean up dependencies?

$ go mod tidy

Go Memory Model?

Go 1.19 introduces a revised memory model and new types that make it easier to use atomic values. With Go 1.19, the language's memory model has been revised to align Go with the memory model used by C, C++, Java, JavaScript, and Swift. https://tip.golang.org/doc/go1.19

What are Go's env variables?

To get env:

$ go env
  • GOROOT: specifies where your GO SDK is located.
  • GOPATH: specifies the root of your workspace (where your packages and dependencies are located).

Vendor

The vendor folder is auto created by go mod vendor:

  • Dependencies in go.mod will be downloaded in vendor folder.
  • go mod vendor also creates the file vendor/modules.txt that contains a list of vendored packages and the module versions they were copied from.
    • When vendoring is enabled, this manifest is used as a source of module version information, as reported by go list -m and go version -m.

Vendoring:

  • enabled by default if the go version in the main module's go.mod file is 1.14 or higher.
  • To explicitly enable vendoring, invoke the go command with the flag -mod=vendor.

When vendoring is enabled, build commands like go build and go test load packages from the vendor directory instead of accessing the network or the local module cache.

How to build CLI applications in Go?

Use Cobra (https://github.com/spf13/cobra), which is used in Kubernetes.

And use Viper (https://github.com/spf13/viper) to manage configurations.

How to get env variables in Go?

Use os.LookupEnv().

How to distinguish 0 and not present

if seconds, ok := timeZone[tz]; ok {
    return seconds
}

test if exists:

_, present := timeZone[tz]

Is Go Object Oriented?

Go is Object Oriented, but not in the usual way.

  • no classes (methods may be declared on any type)
  • no subtype inheritance
  • interfaces are satisfied implicitly (structural typing)

How to check if executables are on PATH?

import (
	"os/exec"
)
func checkExecutableOnPath(cmd string) error {
	if _, err := exec.LookPath(cmd); err != nil {
		// Example error:
		// exec: "cmd": executable file not found in $PATH
		return err
	}
	return nil
}

Is GOPATH deprecated?

Evolution: GOPATH => Modules => Workspaces

GOPATH had been replaced by modules. In 2014, Go development was entirely based on GOPATH. Modules were an answer to many issues around GOPATH. They gave more control to projects on how to track and manage dependencies, and were overall a great step forward.

Multi-module workspaces: With multi-module workspaces, you can tell the Go command that you’re writing code in multiple modules at the same time and easily build and run code in those modules. Once enrolled in a workspace, Go tools had enough information to work in any directory structure and across modules, without GOPATH or symlinks or other dirty tricks. Use go.work to specify a workspace. (Created by go work init PATH). The go.work file has similar syntax to go.mod.