Skip to content

Instantly share code, notes, and snippets.

@krfong916
Last active January 2, 2022 09:32
Show Gist options
  • Save krfong916/a353a324bd96ad792be003e6b7ec7dbc to your computer and use it in GitHub Desktop.
Save krfong916/a353a324bd96ad792be003e6b7ec7dbc to your computer and use it in GitHub Desktop.

Hot Golang

Concurrency

Buffered v. Unbuffered Channels

The choice between unbuffered and buffered channels, and the choice of a buffered channel's capacity, may both affect the correctness of a program.

Unbuffered channels give stronger synchronization guarantees because every send operation is synchronized with its corresponding receive With buffered channels, the send and receive operations are decoupled. When we know an upper bound on the number of values that will be sent on a channel, it's not unusual to create a buffered channel of that size and perform all the sends before the first value is received. Failure to allocate sufficient buffer capacity would cause the program to deadlock.

Packaging cake example * Channel buffering may also affect program performance. Imagine three cooks in a cake shop, one baking, one icing, and one inscribing each cake before passing it on to the next cook in the assembly line:

In a kitchen with little space, each cook that has finished a cake must wait for the next cook to become ready to accept it. This is analogous to communication over an unbuffered channel. If there is space for one cake between each cook, a cook may place a finished cake there and immediately start work on the next. This is analogous to a buffered channel with capacity 1. As long as the cooks work at about the same rate on average, most of these handovers proceed quickly, smoothing out transient differences in their respective rates. More space between cooks (larger buffers) can smooth out bigger transient variations in their rates without stalling the assembly line, such as happens when one cook takes a short break, then later rushes to catch up. On the other hand, a buffer provides no benefit in either of the following case:

When an earlier stage of the assembly line is consistently faster than the following stage, the buffer between them will spend most of its time full. When a later stage is faster, the buffer will usually be empty.

What's the difference between a Pointer receiver vs. Value Receiver?

// pointer receiver - *Type
func (t *Type) Foo() {}

Why are some functions capitalized and some functions lowercased?

  • If you want to the function to be exported in the package, capitalize. You can still use the method by the package, but it won't be exported for use in other packages.
  • Example: func (m *Master) assignMapTask(reply *MRTaskReply) and func(m *Master) RequestTask(args *MRTaskArgs, reply *MRTaskReply) {}

Difference between * and &? Please help me understand

Goroutines (Threads) and Sync Primitives

  • WaitGroup
  • sync.Cond()
mu.Lock()
// do something to produce/change data
sync.Broadcast()
mu.Unlock()
---------
mu.Lock()
while condition == false {
  sync.Wait() // will periodically wake up when sync.Broadcast() is called to check if the condition has been satisfied
}
// when the condition is satisfied, we hold the lock and can safely make updates
mu.Unlock()
  • Channels - Producer/Consumer pattern. Roughly the same as a thread-safe FIFO queue

Make a set

  • make(map[key-type]bool)

Naming conventions

  • If a function begins with an uppercase, the function is a member of your public API
  • If a function is a lowercase, it is an internal helper method

Files

  • Remember to close files. It's necessary when the receiver must be told there are no more values coming

Temp file

  • Why a temp file? There is absolutely no difference between a temporary file and a regular file. The creation of a temp file suggests that the data contained within the file is temporary and not needed beyond the lifetime of the process that created it.
  • Creates a new temp file within the directory. Opens the file for reading and writing. It is the caller's responsibility to remove the file when it is no longer needed
  • Usage: ioutil.TempFile(dir, pattern string)

RPCs

  • Why arg and reply?
  • Things to consider: Make sure you understand why TCP doesn't solve the problem of lost messages, and the ramifications on the semantics of operations. Meditate a bit on the tradeoffs of RPC. What are the costs? Where does it's goal of transparency breakdown? When would one-way messages be better? Why are synchronous RPC calls a bad idea in many cases? What is the impact on the threading/concurrency model if RPCs are not synchronous? Take a look at Go's async RPC facility (see the rpc.Client.Go method).

What is an .so file?

  • A go plugin is a library that we can call/use during runtime. Go packages can be compiled as a shared object library (an .so file), and used dynamically in your application. What does dynamically mean?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment