Logical operators

February 20, 2024

Logical operators

Logical operators apply to boolean values and yield a result of the same type as the operands. The left operand is evaluated, and then the right if the condition requires it.

&&    conditional AND    p && q  is  "if p then q else false"
||    conditional OR     p || q  is  "if p then true else q"
!     NOT                !p      is  "not p"

I think this is pretty intuitive. I mean, it’s only logical, after all….

The most important thing I think to call out here is that the order of operations matters. The right condition(s) are only executed if they need to be. This can matter if you have an expensive operation in your list:

func isValid(t Thing) bool {
	var valid bool
	/*
		Do some expensive validation on t to ensure it's valid.
		Perhaps querying a database, or a remote API call.
	*/
	return valid
}

/* then later */

if isValid(t) && time.Now().Before(deadline) {
	/* Do something */
}

In this example, it would probably be better to re-order the conditional:

if time.Now().Before(deadline) && isValid(t) {

Because in this case, we only have to do the expensive isValid call if the deadline has not passed.

Quotes from The Go Programming Language Specification Language version go1.22 (Feb 6, 2024)


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Order of Evaluation

Let’s talk about… the order of evaluation! You might think you have a strong grasp on this concept, but many languages have their own nuanced take on evaluation order in some cases. And then JavaScript has “hoisting”, which kinda spits in the face of order of evaluation. Before we dive in, here’s a short pop-quiz. What does this short program output when executed? package main import "fmt" func init() { fmt.


The Context API contract

Today we come to the core of the context package: The Context interface itself. type Context type Context interface { Deadline() (deadline time.Time, ok bool) Done() <-chan struct{} Err() error Value(key any) any } A Context carries a deadline, a cancellation signal, and other values across API boundaries. Context’s methods may be called by multiple goroutines simultaneously. For clarity, I’ve removed all of the documentation for each of the interface methods in the above quote—we’ll get to those in following emails, and include those there.


Contexts with timeouts

func WithTimeout func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). Canceling this context releases resources associated with it, so code should call cancel as soon as the operations running in this Context complete: func slowOperationWithTimeout(ctx context.Context) (Result, error) { ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) defer cancel() // releases resources if slowOperation completes before timeout elapses return slowOperation(ctx) } Not only is WithTimeout conceptually similar to WithDeadline, it literally is WithDeadline, as we can see form the source code:

Get daily content like this in your inbox!

Subscribe