True: Go Spec: Blocks (which means you can do stuff like this.
False: The Go Blog: Defer, Panic, and Recover
A deferred function's arguments are evaluated when the defer statement is evaluated.
recover()
will return what panic()
received & resume execution.
True: The Go Blog: Defer, Panic, and Recover
Recover is a built-in function that regains control of a panicking goroutine...During normal execution, a call to recover will return nil and have no other effect. If the current goroutine is panicking, a call to recover will capture the value given to panic and resume normal execution.
True: The Go Blog: Defer, Panic, and Recover
Recover is only useful inside deferred functions.
False: The Go Blog: Defer, Panic, and Recover
Deferred function calls are executed in Last In First Out order after the surrounding function returns.
False: The Go Blog: Defer, Panic, and Recover
Deferred functions may read and assign to the returning function’s named return values.
False: The Go Spec: Program Execution
Program execution begins by initializing the program and then invoking the function main in package main. When that function invocation returns, the program exits. It does not wait for other (non-main) goroutines to complete.
TRUE
type Point struct { X, Y int }
why would this code make any self-respecting gopher cringe? p := Point{1, 2}
The assignment statement utilizes a composite literal (see the Go Spec: Composite Literals. When a struct type is initialized using a composite literal:
An element list that does not contain any keys must list an element for each struct field in the order in which the fields are declared.
The above is a very rigid requirement. Always specifying keys (field names) in struct literals is a much more flexible way to code and allows for the addition and re-ordering of fields without breaking any calling code.
Clear is better than clever. Reflection is never clear.
What is go fmt
? (see the Go Proverbs)
Concurrent execution refers to the capability of the runtime to multi-task when presented with, for instance, blocking I/O. Parallelism refers to executing multiple tasks at the same time (using multiple processors/threads). A concurrent program written in Go can be executed in parallel simply by ensuring that GOMAXPROCS
is greater than 1
(the default value since Go 1.5 has been the number of cores available).
strings.NewReplacer()
function panics if an odd number of arguments are passed. Is this a good approach?
It certainly seems odd for a standard library function such as this to panic if passed an odd number of arguments. Perhaps it would be better to have defined the function with an error return value:
def NewReplacer(args ...string) (*Replacer, error) {...}
Because of the Go 1.0 compatibility promise, the signature for this function won't be changing anytime soon, but we could create a custom 'builder' to smooth this out, something with a Register(search, replace string)
method.
fmt.Sprintf("%s", reflect.TypeOf(a))
but without any call to reflect.TypeOf()
?
fmt.Sprintf("%T", a)
True
False (only when neither is a string)
csv.NewReader(bufio.NewReader(file))
Since the csv.NewReader function wraps the provided reader in bufio.NewReader for the caller, it's sufficient to simply use csv.NewReader(file)
.
strings.Split(s, "\t\n\v\f\r ")
strings.Fields(s)
strings.Replace(s, "a", "b", -1)
strings.ReplaceAll(s, "a", "b")
a := new(Thing)
is equivalent to a := Thing{}
False! The new
function returns a pointer.
var a any = new(Thing)
is equivalent to var a any = reflect.New(reflect.TypeOf(Thing{})).Interface()
True! The reflect.New
function is analogous to the built-in new
function. They both return pointers to a newly allocated zero-value of the provided type.
t1 := T{}; t2 := reflect.ValueOf(t1).Interface(); fmt.Print(t1 == t2)
True! See "The Laws of Reflection".
int
?
The answer is dependent upon processor architecture. Most likely your int values have 64 bits, unless the architecture of your processor is 32-bit.
while
is spelled ___
.
There are 3 forms of the for
loop in Go. The one called "For statements with single condition" operates the same as while
loops common in other languages.
False! The point of compiling a regular expression is so you can then reuse it many times. In my own benchmarks, compiling a simple regex takes ~800ns while matching against a string with the compiled regex only takes ~80ns (that's a 10x difference). So, for simple regular expressions and small strings, it's very advantageous to pre-compile the regular expression pattern once and then reference it as needed later. Moral of the story: Don't call regexp.Compile(...)
every time you want to perform a match.
Try writing your own benchmarks to see how the complexity of a regular expression pattern and the length of the text against which you match affect runtime. (The results may surprise you!)
io.EOF
stand for and in what scenarios might that be something of a misnomer?
End of file. It is a slight misnomer in the context of any io.Reader
whose underlying source is NOT an instance of *os.File
. Perhaps this is why, in the official io
package documentation, the acronym is never explicitly decoded.
any
is an alias for interface{}
and is equivalent to interface{}
in all ways.
make(map[k]v)
is the same as map[k]v{}
False! The zero value will be returned (without any panic).
False! The zero value will be returned.
False! Concurrent map access must be protected by a mutex. Alternatively, you could consider using sync.Map.
True! This is a handy way to index values by a combination of key properties.
True! It is also not guaranteed to be the same from one iteration to the next.
B. The sync.WaitGroup is effectively a fancy (i.e. 'thread-safe') Counter with some pretty specific rules about how it should be used.
False! Add should be called from the 'main' goroutine and should not be called while a call to Wait() is blocked.
True, but only if you like code that panics. In practice, Done should only be called once from each awaited goroutine, usually as a deferred call.
False, there is no timeout. It blocks until all awaited goroutines finish. End of story.
True! Don't get fancy with a WaitGroup. Use it to wait for a batch of goroutines. Only after Wait has unblocked may you use the same instance to wait for another batch of goroutines.
False! You must call recover
somewhere higher in the call stack of panicking goroutine, otherwise the program will crash.
False! A single Git repository may contain multiple Go module definitions.
True! It is only once a module graduates to 'v1.*.*' that module developers must be conscious of backward compatibility.
False! Once a module reaches 'v2.*.*' it must contain '/v2' in its module declaration and package import paths. Modules at 'v0.*.*' or 'v1.*.*' are not subject to any such requirement.
"copying"
"values"
"weaker"
const a = "b"
True! See Constants on the Go blog.
True! Generics in Go (aka "type parameters") enable writing reusable code that can work with various data types. Common example: a function that can operate on a slice of any item type.
False. Go's generics are statically typed, meaning type information is determined at compile time.
False. Generics in Go can be used with user-defined types as well, providing flexibility in creating generic algorithms and data structures.
False. Go 1.18 introduced generics as an official feature, but a few packages were released as 'experimental' on the golang.org/x/exp subrepository (constraints/slices/maps) to allow developers to use and provide feedback on real-world scenarios. Much of the code defined in those experimental packages has been incorporated into the standard library since then.
This question can be found at the Go Playground, but here's the relevant snippet of code:
date_2023_01_30 := time.Date(2023, time.January, 30, 0, 0, 0, 0, time.UTC)
one_month_later := date_2023_01_30.AddDate(0, 1, 0)
date_2023_02_28 := time.Date(2023, time.February, 28, 0, 0, 0, 0, time.UTC)
fmt.Println("T/F?", one_month_later == date_2023_02_28)
False! The one_month_later
value is equal to "2023-03-02"
. From the docs:
AddDate
normalizes its result in the same way thatDate
does, so, for example, adding one month to October 31 yields December 1, the normalized form for November 31.
make(chan int)
is equivalent to make(chan int, 1)
.
False! make(chan int)
is equivalent to make(chan int, 0)
.
False! A send to a nil channel blocks forever. See Channel Axioms, by Dave Cheney
False! A receive from a nil channel blocks forever. See Channel Axioms, by Dave Cheney
True! See Channel Axioms, by Dave Cheney
False! A receive from a closed channel returns the zero value immediately. See Channel Axioms, by Dave Cheney
True! See Curious Channels, by Dave Cheney
False! A nil channel always blocks. See Curious Channels, by Dave Cheney
False! Unlike other languages that are more object-oriented, a Go method is essentially just a function which receives the 'receiver' as a regular (though somewhat obscured) argument. It is only when a field on the nil receiver is accessed that a panic will occur.
*testing.T.Fail()
ends the currently executing test immediately.
False. The Fail method only marks the test as failed. The test will continue execution.
*testing.T.Fatal()
panics immediately.
False. The Fatal method ends a test immediately, but without panicking.
log.Println(fmt.Sprintf("Hello, %s.", name))
log.Printf("Hello, %s.", name)
-Michael Whatcott