Mocking Http requests in go

Mocking http retries behavior As we know, http requests can fail for a large variety of reasons, client side or server side (unauthorized, timeouts etc). On the client side a common approach is to retry request by increasing the waiting time between retries. Is this scenario be easily unit test? Unit Testing In golang there is this cool library Simple mocking of an http endpoint: func TestMockHttpResponse(t *testing.T) { httpmock.Activate() defer httpmock.DeactivateAndReset() httpmock.RegisterResponder("GET", "http://example.com/articles", httpmock.NewStringResponder(200, "my articles").String())) resp, err := http.Get("http://example.com/") // return http 200 ... } But there is more, we can actually easily mock retries like this below: ...

April 10, 2023 · 1 min · Nolan

Monkey Patching in Golang

Monkey Patching As I’ve seen monkey patching is not advise in golang but it is possible here is a simple example. Code to test: package main var version = func(test string) string { return "true version" + test } func getVersion() string { return version("test") } Test package main import ( "testing" ) func TestVersion(t *testing.T) { oldfunction := version defer func() { version = oldfunction }() version = func(name string) string { return "fake return output" } if getVersion() != "fake return output" { t.Fatalf("failed" + getVersion()) } }

September 27, 2022 · 1 min · Nolan

Golang, Adding static content in binaries

Embed directive When building a binary, if you load config files, they won’t be added to your binary automatically. (The embed package was added in golang 1.16 before then some external libraries could be used). You have to specifically tell the compiler to add them, by using embed. import _ "embed" //go:embed my_config.yaml var config string From what I’ve seen, it cannot be done in a function it has to be global. It can also work on multiple files, by using a wildcard, as seen in the documentation ...

September 9, 2022 · 1 min · Nolan

Sending a slow request

Sending Slow request in golang I thought it was a cool snippet that I wanted to share and keep (AKA slow loris attack). The http Post method takes an io.reader that could be overridden. It could be used to test how your web application reacts in those situations, does it hangs? timeouts? Http Post definition: func (c *Client) Post(url, contentType string, body io.Reader) (resp *Response, err error) Taking a Read function as example from https://go.dev/src/bytes/buffer.go#L297 ...

February 23, 2022 · 1 min · Nolan

Using Variadic in Go

Nothing new Variadic arguments are present in many many languages. In golang the syntax is like so: package main import "fmt" func addNubers(nums ...int) int { s := 0 for _, n := range nums { s += n } return s } func main() { res := addNubers(1,2,3) } In python: def func(a, *t): for e in t: print(e) func(1,2,3,3,4) Usage in go In go variadic functions are used to make configuration easily extendable, without changing existing interface. By doing so we can easily add options without breaking existing code. ...

October 3, 2021 · 1 min · Nolan

Go testing

Testing in golang Simple test in go package main import "testing" func add(a, b int) int { return a + b } func TestAddingNumber(t *testing.T) { res := add(1, 7) if res != 8 { t.Errorf("Sum is incorrect, got: %d, expected: %d", res, 8) } } Run tests: go test -v ./... Avoiding repeating tests Instead of duplicating code for similar tests, there is a different way to test. package main import ( "strings" "testing" ) func rep(s string) string { return strings.Replace(s, "b", "c", -1) } func TestFiles(t *testing.T) { tests := []struct { testName string oldConfigVal string newConfigVal string err error }{ {"Testing First config", `a:b`, `a:c`, nil}, {"Tesing second config", `e:f`, `e:f`, nil}, } t.Run("Test config replaced correctly", func(t *testing.T) { for _, tc := range tests { t.Run(tc.testName, func(t *testing.T) { res := rep(tc.oldConfigVal) t.Log(res, tc.newConfigVal) if res != tc.newConfigVal { t.Errorf("unable to read file") } }) } }) }

October 2, 2021 · 1 min · Nolan

Golang Encoding/Decoding JSON

Encoding JSON Encoding Decoding is not as straight forward as other languages as it needs to be mapped to a struct. Or a generic map[interface] can be used if you don’t know the type in advance. package main import ( "encoding/json" "fmt" ) type Data struct { Id int `json:"id"` List []string `json:"list"` NotPrint string `json:"-"` } func main(){ d := Data{Id: 123, List: []string{"abc", "b"}, NotPrint: "This won't print"} result, err := json.MarshalIndent(d, "","\t") if err != nil { panic(err) } fmt.Printf("%s\n", result) } Decoding JSON package main import ( "encoding/json" "fmt" ) type Data struct { Id int `json:"id"` List []string `json:"list"` NotPrint string `json:"-"` } var b = []byte(` { "id" : 123, "list": ["a", "b", "c"] } `) func main() { var d Data valid := json.Valid(b) if valid { json.Unmarshal(b, &d) fmt.Printf("%#v", d) } }

September 25, 2021 · 1 min · Nolan

Go templates

Templating with Sprig Templating can be useful, for instance it is heavily used in helm. Below a simple example to get started, sprig is just library on top of golang templating that provides extra functions. package main import ( "os" template "text/template" "github.com/Masterminds/sprig" ) var temp = ` start {{ .Title | repeat 2 | indent 2}} {{ .Text }} {{ first .List }} end ` type Values struct { Title string Text string List []int } func main() { t, err := template.New("todos").Funcs(sprig.GenericFuncMap()).Parse(temp) if err != nil { panic(err) } s := make([]int, 0) s = append(s, 1) v := Values{Title: "The title", Text: "Txt", List: s} err = t.Execute(os.Stdout, v) if err != nil { panic(err) } } Full code is there gitlab ...

September 24, 2021 · 1 min · Nolan

Tickers

Tickers I was looking into timers and I came across tickers. Basically they allow you to trigger an event at a regular time interval. One simple example could be some kind of monitoring. What’s interesting is that it pushes a Ticker to a channel. Here is a basic example: package main import ( "fmt" "os" "sync" "time" ) func checkInBackground(ticker time.Ticker, wg *sync.WaitGroup) { wg.Add(1) for ; true; <-ticker.C { fmt.Println("ok") } wg.Done() } func termination() { os.Exit(1) } func main() { var wg sync.WaitGroup ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() go checkInBackground(*ticker, &wg) time.AfterFunc(time.Duration(10)*time.Second, termination) wg.Wait() fmt.Println("Done as expected") } Not sure if it’s a nice way to achieve that as I’m learning Golang, but I did what I wanted. ...

August 30, 2021 · 1 min · Nolan

Using GOPROXY

Getting dependencies via GOPROXY I recently wanted to use a private registry in a go project. It can be for many reasons: ensure immutability from one built to another ensure avaibility of a build (remember npm author who removed his library and broke half the internet?) get non-public library How it works Quick & Easy It is super easy you just have to add an env variable: export GOPROXY="myprivateserver.com/registry/api/go/go" You can then do a: ...

April 19, 2021 · 1 min · Nolan