Last active
April 7, 2020 05:41
-
-
Save doron2402/dc3905574449bfb3bfffff2daf035533 to your computer and use it in GitHub Desktop.
Golang sync package - example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
/** | |
A cool way to find out if there are any race condition is using | |
`go run --race .` | |
**/ | |
import ( | |
"fmt" | |
"math/rand" | |
"sync" | |
"time" | |
) | |
// cache - key value (key = book id, value = book object) | |
var cache = map[int]Book{} | |
// get random instance | |
var rnd = rand.New(rand.NewSource(time.Now().UnixNano())) | |
func main() { | |
wg := &sync.WaitGroup{} | |
m := &sync.RWMutex{} | |
for i := 0; i < 10; i++ { | |
id := rnd.Intn(10) + 1 | |
// set 2 waiting group (1. cache, 2. db) | |
wg.Add(2) | |
go func(wg *sync.WaitGroup, m *sync.RWMutex) { | |
if b, ok := queryCache(id, m); ok { | |
fmt.Println("from cache") | |
fmt.Println(b) | |
} | |
// if the book found in cache finish the waiting group | |
wg.Done() | |
}(wg, m) | |
go func(wg *sync.WaitGroup, m *sync.RWMutex) { | |
// get book from db | |
if b, ok := queryDatabase(id, m); ok { | |
fmt.Println("from database") | |
fmt.Println(b) | |
} | |
// finish waiting group | |
wg.Done() | |
}(wg, m) | |
// time.Sleep(150 * time.Millisecond) | |
} | |
// wait for all concurrent functions | |
wg.Wait() | |
} | |
func insertBook(books Book[], b Book) Book[] { | |
books = append(books, book) | |
return books | |
} | |
func queryCache(id int, m *sync.RWMutex) (Book, bool) { | |
m.RLock() | |
b, ok := cache[id] | |
m.RUnlock() | |
return b, ok | |
} | |
func queryDatabase(id int, m *sync.RWMutex) (Book, bool) { | |
time.Sleep(100 * time.Millisecond) | |
for _, b := range books { | |
if b.ID == id { | |
m.Lock() | |
cache[id] = b | |
m.Unlock() | |
return b, true | |
} | |
} | |
return Book{}, false | |
} | |
// books.go | |
package main | |
import "fmt" | |
type Book struct { | |
ID int | |
Title string | |
Author string | |
YearPublished int | |
} | |
func (b Book) String() string { | |
return fmt.Sprintf( | |
"Title:\t\t%q\n"+ | |
"Author:\t\t%q\n"+ | |
"Published:\t%v\n", b.Title, b.Author, b.YearPublished) | |
} | |
var books = []Book{ | |
Book{ | |
ID: 1, | |
Title: "The Hitchhiker's Guide to the Galaxy", | |
Author: "Douglas Adams", | |
YearPublished: 1979, | |
}, | |
Book{ | |
ID: 2, | |
Title: "The Hobbit", | |
Author: "J.R.R. Tolkien", | |
YearPublished: 1937, | |
}, | |
Book{ | |
ID: 3, | |
Title: "A Tale of Two Cities", | |
Author: "Charles Dickens", | |
YearPublished: 1859, | |
}, | |
Book{ | |
ID: 4, | |
Title: "Les Misérables", | |
Author: "Victor Hugo", | |
YearPublished: 1862, | |
}, | |
Book{ | |
ID: 5, | |
Title: "Harry Potter and the Philosopher's Stone", | |
Author: "J.K. Rowling", | |
YearPublished: 1997, | |
}, | |
Book{ | |
ID: 6, | |
Title: "I, Robot", | |
Author: "Isaac Asimov", | |
YearPublished: 1950, | |
}, | |
Book{ | |
ID: 7, | |
Title: "The Gods Themselves", | |
Author: "Isaac Asimov", | |
YearPublished: 1973, | |
}, | |
Book{ | |
ID: 8, | |
Title: "The Moon is a Harsh Mistress", | |
Author: "Robert A. Heinlein", | |
YearPublished: 1966, | |
}, | |
Book{ | |
ID: 9, | |
Title: "On Basilisk Station", | |
Author: "David Weber", | |
YearPublished: 1993, | |
}, | |
Book{ | |
ID: 10, | |
Title: "The Android's Dream", | |
Author: "John Scalzi", | |
YearPublished: 2006, | |
}, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment