Category Archives: golang
Another cool article on using PostgreSQL+pgBouncer with go
Extremely interesting and very practical talk about problems occurring with go+pgBouncer (in Russian, sorry). https://habr.com/ru/company/oleg-bunin/blog/461935/ And a video on that: https://www.youtube.com/watch?v=Uojy57I-xP0
env-file parser for Goland
You can use env-file parser for running and debugging your app in Jetbrains’ products like Goland. It’s pretty simple and works. https://github.com/Ashald/EnvFile
How golang garbage collection works
It is a Mark-and-Sweep GC. Phases Mark Stop-the-World: Set write barrier (to know how much was allocated during maark phase) Concurrent: Mark all memory which is still in use by the app Stop-the-World: Remove write barrier Concurrent: Sweep (it actually happens on new allocations) Details/Algorithm It’s a tri-color process: grey for objects to check, black …
Style guide for golang project file structure
Highly recommended. It has a couple of odds like not explaining about /test dir (I assume, they wanted to say to put there only e2e and other integrational tests, not unit-test as the latter should be kept together with the code itself in files like …_test.go). But it’s awesome in general. https://github.com/golang-standards/project-layout
Golang patterns. Worker pool
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Println("worker", id, "started job", j) time.Sleep(time.Second) fmt.Println("worker", id, "finished job", j) results <- j * 2 } } func main() { // In order to use our pool of workers we need to send // them work and collect their results. We make 2 // channels for this. jobs := make(chan int, 100) results := make(chan int, 100) // This starts up 3 workers, initially blocked // because there are no jobs yet. for w := 1; w <= 3; w++ { go worker(w, jobs, results) } // Here we send 5 `jobs` and then `close` that // channel to indicate that's all the work we have. for j := 1; j <= 5; j++ { jobs <- j } close(jobs) for a := 1; a <= 5; a++ { <-results } } |
Further reading: https://gobyexample.com/worker-pools
PgBouncer and prepared statements
In our system, we use connection pooler called PgBouncer as a proxy to PostgreSQL server. PgBouncer has two main modes Session pooling mode This mode is less performant (it’s a default mode). When a client connects, a server connection will be assigned to it for the whole duration it stays connected. So it does not …
Golang: testing http and grpc servers
HTTP server is quite easy to test — here is a nice video about it:
How go code is being compiled to assembler code
https://go.godbolt.org/z/31FyJ3 I was interested in comparing line 15 vs line 17 of the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package main import "fmt" type kv struct { key []byte value []byte } type sliceMap []kv func (sm *sliceMap) Add(k, v []byte) { kvs := *sm if cap(kvs) > len(kvs) { kvs = kvs[:len(kvs)+1] } else { kvs = append(kvs, kv{}) } kv := &kvs[len(kvs)-1] kv.key = append(kv.key[:0], k...) kv.value = append(kv.value[:0], v...) *sm = kvs } func main() { sm := sliceMap{} sm.Add([]byte("foo"), []byte("bar")) fmt.Println(sm) } |
E2E tests in go
I tried it via ginkgo and gomega. It has Agouti with WebDriver support out of the box, but I didn’t use it as we have grpc API. That’s the example (table tests):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
var _ = Describe("GetRoute", func() { var ( srClient sr.Client srErr error ) JustBeforeEach(func() { srClient, srErr = GetClient() }) DescribeTable("positive cases", func(fromGeoPointID, toGeoPointID int, expectedUID string, expectedCostGreaterThan float64) { Expect(srErr).NotTo(HaveOccurred()) Expect(srClient).NotTo(BeNil()) response, err := srClient.GetRoute(context.TODO(), &sr.GetRouteRequest{ FromGeoPointId: int64(fromGeoPointID), ToGeoPointId: int64(toGeoPointID), Quantity: 1, Volume: 1, Weight: 1, }) Expect(err).To(Succeed()) Expect(response).NotTo(BeNil()) Expect(response.RouteCost).NotTo(BeNil()) Expect(response.RouteCost.RouteUid).To(HaveSuffix(expectedUID)) Expect(response.RouteCost.GetCost()).To(BeNumerically(">", expectedCostGreaterThan)) }, Entry("from(geo=3)->to(geo=2)", 3, 2, "-3-2", float64(10)), ) |
ORM for go
https://github.com/Masterminds/squirrel Never used it as we always write SQL queries manually. But looks okay for ORM (well, actually a query-builder).