1. What is a goroutine? How do you stop it?#
- A goroutine is a function or method that runs concurrently with other goroutines. Goroutines are lighter weight than standard threads, and most Golang programs use thousands of goroutines simultaneously.
- To create a goroutine, add the keyword "go" before the function declaration.
- You can stop a goroutine by sending a signal on a channel. Goroutines only respond to signals when they are instructed to check, so you need to include the check at a logical position (e.g., at the top of a for loop).
2. What are the characteristics of a sync lock? What is its purpose?#
- In Go, communication is achieved through channels rather than shared memory. Go's Communicating Sequential Process (CSP) concurrency model is implemented using goroutines and channels.
- When a goroutine acquires a mutex, other goroutines must wait until the mutex is released. RWMutex allows multiple readers or a single writer at a time. While a write lock is held, no other goroutine (read or write) can enter, ensuring exclusive access to the synchronized lock and maintaining system stability.
3. What are the characteristics of a channel? What should be noted?#
- Sending data on a nil channel will cause a permanent block.
- Receiving data from a nil channel will also cause a permanent block.
- Sending data on a closed channel will cause a panic.
- Receiving data from a closed channel will return a zero value if the buffer is empty.
4. What is GoConvey? What is it commonly used for?#
- GoConvey is a unit testing framework for Golang.
- GoConvey can automatically monitor file changes and start tests, and it can display test results in real-time on a web interface.
- GoConvey provides rich assertions to simplify the writing of test cases.
5. What is the difference between make and new in Go?#
- Both make and new are used for memory allocation.
- make is used for initializing slices, maps, and channels, and it returns the initialized reference type itself.
- new is used for allocating memory for a type and initializes the memory to the zero value of the type, returning a pointer to the type.
6. What is the difference between an array and a slice in Go?#
- Array:
- Arrays have a fixed length. The length is part of the array type, so [3]int and [4]int are different types. Arrays need to specify the size, but if not specified, the size can be automatically inferred based on the initialization. Arrays are passed by value.
- Slice:
- Slices can change their length. Slices are lightweight data structures with three properties: pointer, length, and capacity. Slices do not need to specify a size. Slices are passed by reference and can be initialized using an array or the built-in function make(), where the length is equal to the capacity, and then it can be expanded.
7. What is the purpose and characteristics of defer?#
- The purpose of defer is to delay the execution of a function until the surrounding function returns. When a defer statement is executed, the function following the defer keyword is deferred until the surrounding function completes, regardless of whether the completion is normal or due to a panic. Multiple defer statements can be used in a function, and they are executed in reverse order of declaration.
- Common use cases for defer include handling paired operations such as opening and closing, connecting and disconnecting, locking and unlocking.
- By using defer, resources can be released in any execution path, ensuring resource cleanup and system stability.
- Defer statements should be placed immediately after the request for the resource.
8. How to use WaitGroup?#
A WaitGroup object can wait for a group of goroutines to finish. The usage is as follows:
- The main goroutine calls wg.Add(delta int) to set the number of worker goroutines and then creates the worker goroutines.
- After the worker goroutines finish their execution, they call wg.Done().
- The main goroutine calls wg.Wait() and blocks until all worker goroutines have completed.
9. How does WaitGroup work?#
- WaitGroup maintains two counters: a request counter (v) and a wait counter (w). They form a 64-bit value, with the request counter occupying the higher 32 bits and the wait counter occupying the lower 32 bits.
- Each call to Add increments the request counter (v), and each call to Done decrements the wait counter (w). When v becomes 0, Wait() is unblocked.
10. What is sync.Once?#
- sync.Once is used to perform and ensure that an action is performed only once. It is commonly used for initializing singleton objects.
- By calling the Do method multiple times, only the first call to Do will execute the function (f) provided. The function should be a parameterless function with no return value.
11. What is an atomic operation?#
An atomic operation is an operation that cannot be interrupted during its execution. It is represented and completed by a single CPU instruction. Atomic operations are lock-free and often directly implemented using CPU instructions. Other synchronization techniques often rely on atomic operations.
12. What is the difference between atomic operations and locks?#
- Atomic operations are supported by the underlying hardware, while locks are implemented by the operating system's scheduler. Locks are used to protect a section of code or update a variable.
- Atomic operations are generally more efficient and can take advantage of the multi-core capabilities of a computer. If updating a complex object, it is recommended to use the atomic.Value implementation.
13. What is a microservice?#
A microservice, also known as a microservices architecture, is an architectural style that structures an application as a collection of small, autonomous services based on business domains.
In simple terms, think of how bees build their honeycomb by aligning hexagonal wax cells. They start with small portions made of various materials and build a larger hive from them. These cells form patterns and create a strong structure that holds specific parts of the honeycomb together.
Here, each cell is independent of the other cells but also related to them. This means that damage to one cell does not affect the others, allowing bees to rebuild the cells without compromising the integrity of the entire hive.