- Go provides built-in channels for goroutines to communicate safely between themselves.
- More goroutines can run on a typical system than system threads. For example, with Java, you can run many thousands of threads. With Go, you can run many millions of goroutines.
- Goroutines startup more quickly than operating system threads. Multiple Goroutines are multiplexed onto OS threads, rather than a 1:1 mapping.
- You can write massively concurrent servers without having to resort to event programming.
- Goroutines are not hardware-dependent like threads.
- Goroutines are more lightweight, largely due to segmented stacks in memory
- Constants can not be computed at runtime, their value must be known at compile time. That said, constants can be computed at compile-time, typically as a derivative of other constants.
const hours = 7643
const minutes = hours * 60
var1, var2 = var2, var1
Errors in Go are an interface type, where any type that implements the single Error()
method can be considered an error.
Whenever a function has a possibility to go wrong, like a network call or a type conversion, the function should return an error as its last return variable. The caller should check the error value, and any value other than nil is considered an error.
Idiomatic Go developers should prefer guard clauses over if-else chains, especially when handling errors. Errors should also be wrapped in a meaningful way as they are passed up the call stack if appropriate.
A pointer holds the memory address of a value.
&
generates a pointer to its operand.*
dereferences a pointer (exposes the underlying value).
Pointers can be used to:
- Allow a function to directly mutate a value that is passed to it
- To increase performance in edge cases. Sometimes passing a large struct of data results in inefficient copying of data
- To signify the lack of a value. For example, when unmarshalling JSON data into a struct it can be useful to know if a key was absent rather than it being present with the zero value.
Channels are safe for concurrent access, for this reason they have blocking operations. Maps are unsafe for concurrent access and require a locking mechanism like a mutex to be safely used across goroutines.
I would build a new type that represents a slice of that struct type. For example:
type fruitSlice[]fruit
type car struct {
size int
color string
}
Then I would fulfill the standard library’s sort.Interface
:
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
I would then be able to use the sort.Sort
function:
sort.Sort(fruitSlice(cars))
Ask about the persons view on generic programming.
Nope! nil
is the zero value for pointers, interfaces, maps, slices, channels, and function types. nil
represents an uninitialized value.
Exported function in Go just need to be capitalized.
This is a bit of a trick question: there is no inheritance in Golang because it does not support classes.
However, you can mimic inheritance behavior using composition to use an existing struct object to define a starting behavior of a new object. Once the new object is created, functionality can be extended beyond the original struct.
GO is a Structural-typed language. Nice article - https://medium.com/higher-order-functions/duck-typing-vs-structural-typing-vs-nominal-typing-e0881860bf10
Yes. A Go function can return multiple values, each separated by commas in the return statement.
Wrapped errors in Go refer to the practice of adding additional context to an existing error before passing it up the call stack. This is particularly useful in error handling and debugging.
- Error Wrapping: In Go, you can wrap an error using the
%w
verb withfmt.Errorf
. This allows you to add more context to the original error. - Retrieving the Original Error: You can use the
errors.Unwrap
function to retrieve the original error from a wrapped error. - Error Checking: Go provides the
errors.Is
anderrors.As
functions for checking the type or value of an error, including wrapped errors.errors.Is
is used to check if any error in the error chain matches a specific error.errors.As
is used to check if any error in the error chain matches a specific error type. - Use Case: Wrapping errors is useful when you want to maintain the original error information but also provide additional context about what was happening when the error occurred.
import (
"errors"
"fmt"
)
func someFunction() error {
err := anotherFunction() // assume this returns an error
if err != nil {
// Wrapping the error with additional context
return fmt.Errorf("failed to execute anotherFunction: %w", err)
}
return nil
}
// In the caller function
err := someFunction()
if err != nil {
// Checking the specific error type or value
if errors.Is(err, someSpecificError) {
// handle specific error
}
}