1. Concurrency Patterns
Worker Pools
Worker pools allow you to manage a large number of goroutines efficiently by limiting the number of active workers.
package main
import (
"fmt"
"time"
)
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Printf("Worker %d processing job %d\n", id, j)
time.Sleep(time.Second)
results <- j * 2
}
}
func main() {
const numJobs = 5
jobs := make(chan int, numJobs)
results := make(chan int, numJobs)
// Start workers
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// Send jobs
for j := 1; j <= numJobs; j++ {
jobs <- j
}
close(jobs)
// Collect results
for a := 1; a <= numJobs; a++ {
fmt.Println("Result:", <-results)
}
}
Select Statement
The select
statement is used to wait on multiple channel operations.
package main
import (
"fmt"
"time"
)
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
c1 <- "one"
}()
go func() {
time.Sleep(2 * time.Second)
c2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("Received", msg1)
case msg2 := <-c2:
fmt.Println("Received", msg2)
}
}
}
2. Reflection
Reflection in Go allows you to inspect the types of variables at runtime and manipulate objects with dynamic types.
Basic Reflection Example
package main
import (
"fmt"
"reflect"
)
func main() {
var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("Type:", v.Type())
fmt.Println("Kind:", v.Kind())
fmt.Println("Value:", v.Float())
}
Modifying Values with Reflection
To modify a value using reflection, the value must be settable, which means it must be addressable.
package main
import (
"fmt"
"reflect"
)
func main() {
var x float64 = 3.4
p := reflect.ValueOf(&x)
v := p.Elem()
v.SetFloat(7.1)
fmt.Println("Updated value:", x)
}
3. Interfacing with C Libraries
Go can call C libraries using cgo, which is useful for integrating with existing C codebases or libraries.
Calling a Simple C Function
First, create a simple C library. For example, create a file named myclib.c
:
// myclib.c
#include <stdio.h>
void myprint(const char* s) {
printf("%s\n", s);
}
Then create a Go program that uses this C function:
package main
/*
#include <stdio.h>
#include <stdlib.h>
void myprint(const char* s);
*/
import "C"
import "unsafe"
func main() {
msg := C.CString("Hello from C!")
C.myprint(msg)
C.free(unsafe.Pointer(msg))
}