# How to simplify and speed up the Golang module development?

**URL:** <https://forum.heroiclabs.com/t/how-to-simplify-and-speed-up-the-golang-module-development/796>\
**Category:** Game Design\
**Tags:** getting-started, server-framework\
**Created:** [June 11, 2020, 4:47pm UTC](https://forum.heroiclabs.com/t/how-to-simplify-and-speed-up-the-golang-module-development/796 "2020-06-11T16:47:18Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nikola-Milovic](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/nikola-milovic/32/282_2.png) [@Nikola-Milovic](https://forum.heroiclabs.com/u/Nikola-Milovic)\
**Post date:** [June 11, 2020, 4:47pm UTC](https://forum.heroiclabs.com/t/how-to-simplify-and-speed-up-the-golang-module-development/796/1 "2020-06-11T16:47:18Z")

</div>

Godot + Nakama with Golang modules

I’ve just started using Golang with Nakama and it has been a rocky start, nevertheless thanks to the helpful folks over at Gitter I’ve managed to get it running in no time(2days). Now after messing with it for some time I have a couple of questions about development. My process currently looks like this:

 ![image](https://us1.discourse-cdn.com/flex020/uploads/heroiclabs/original/1X/2e3986644788b841002c3397190e81e5cc019344.png)

I have the test.go file that I edit in notepad (no autocomplete…) and whenever I make a change I have to run `docker run --rm -w "/builder" -v "${PWD}:/builder" heroiclabs/nakama-pluginbuilder:2.12.0 build -buildmode=plugin -trimpath -o ./modules/plugin_code.so` and when it’s finished I copy the .so file from the modules dir to the nakama servers modules bin and restart the server. This seems awful and slow especially that I cannot use any of the nakamas autocomplete functions and I have no idea about the syntax they use.

1. How can I speed up or automate this process?
2. Can I use an editor (Atom has support for Go) to get some help while writing the modules?

Any other tips are highly appreciated! Hopefully, this will be helpful to other beginners as well.

---

<div class="post-metadata">

**Author:** ![BeLuckyDaf](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/beluckydaf/32/211_2.png) [@BeLuckyDaf](https://forum.heroiclabs.com/u/BeLuckyDaf)\
**Post date:** [June 11, 2020, 9:44pm UTC](https://forum.heroiclabs.com/t/how-to-simplify-and-speed-up-the-golang-module-development/796/2 "2020-06-11T21:44:04Z")

</div>

Here, check this out. [Setting up Goland to compile plugins on Windows](https://forum.heroiclabs.com/t/setting-up-goland-to-compile-plugins-on-windows/594/5)

There is no goland involved. Just VS Code and Linux, WSL in my case.

This way, it’s just a matter of one second after you run the shell script. Made a change, run it again, one second, boom 💥 you’re up and running again.

---

<div class="post-metadata">

**Author:** ![novabyte](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/novabyte/32/1324_2.png) [@novabyte](https://forum.heroiclabs.com/u/novabyte)\
**Post date:** [June 12, 2020, 12:36am UTC](https://forum.heroiclabs.com/t/how-to-simplify-and-speed-up-the-golang-module-development/796/3 "2020-06-12T00:36:27Z")

</div>

@Nikola-Milovic What I tend to use on Go projects with Nakama is a simple multi-stage Docker file like:

```auto
FROM heroiclabs/nakama-pluginbuilder:2.12.0 AS builder

ENV GO111MODULE on
ENV CGO_ENABLED 1

WORKDIR /backend
COPY . .

RUN go build --trimpath --mod=vendor --buildmode=plugin -o ./backend.so

FROM heroiclabs/nakama:2.12.0

COPY --from=builder /backend/backend.so /nakama/data/modules

```

With a Docker compose file which uses it to build a container of both my custom Go code and package it into the Nakama container:

```auto
version: '3'
services:
  postgres:
    container_name: game_backend_postgres
    environment:
      - POSTGRES_DB=nakama
      - POSTGRES_PASSWORD=localdb
    expose:
      - "8080"
      - "5432"
    image: postgres:9.6-alpine
    ports:
      - "5432:5432"
      - "8080:8080"
    volumes:
      - data:/var/lib/postgresql/data

  nakama:
    build: .
    container_name: game_backend
    depends_on:
      - postgres
    entrypoint:
      - "/bin/sh"
      - "-ecx"
      - >
        /nakama/nakama migrate up --database.address postgres:localdb@postgres:5432/nakama &&
        exec /nakama/nakama --database.address postgres:localdb@postgres:5432/nakama
    expose:
      - "7349"
      - "7350"
      - "7351"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:7350/"]
      interval: 10s
      timeout: 5s
      retries: 5
    links:
      - "postgres:db"
    ports:
      - "7349:7349"
      - "7350:7350"
      - "7351:7351"
    restart: unless-stopped

volumes:
  data:

```

To build the Docker container and run the entire setup in one step it becomes:

```shell
docker-compose -f ./docker-compose.yml up -d --build nakama

```

You can see a full example of it on this gist:

[https://gist.github.com/novabyte/cc6d57022e2d3baa40e98d8fc91dc4c8](https://gist.github.com/novabyte/cc6d57022e2d3baa40e98d8fc91dc4c8)

This does require a bit more commitment to learn how to take advantage of Docker though. As well as knowledge of commands like: `docker ps`, `docker prune ...`, etc, etc.

---

<div class="post-metadata">

**Author:** ![Nikola-Milovic](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/nikola-milovic/32/282_2.png) [@Nikola-Milovic](https://forum.heroiclabs.com/u/Nikola-Milovic)\
**Post date:** [June 12, 2020, 4:28pm UTC](https://forum.heroiclabs.com/t/how-to-simplify-and-speed-up-the-golang-module-development/796/4 "2020-06-12T16:28:23Z")

</div>

Using @novabyte 's answer I’ll pitch in and show it how I got it working with cockroach db.

```auto
version: '3'
services:
 cockroachdb:
   container_name: cockroachdb
   image: cockroachdb/cockroach:v19.2.5
   command: start --insecure --store=attrs=ssd,path=/var/lib/cockroach/
   restart: always
   volumes:
     - data:/var/lib/cockroach
   expose:
     - "8080"
     - "26257"
   ports:
     - "26257:26257"
     - "8080:8080"
 nakama:
   build:
     context: ./../backend
   container_name: game_backend
   depends_on:
     - cockroachdb
   entrypoint:
     - "/bin/sh"
     - "-ecx"
     - >
       /nakama/nakama migrate up --database.address root@cockroachdb:26257 &&
        exec /nakama/nakama --name nakama1 --database.address root@cockroachdb:26257
   expose:
     - "7349"
     - "7350"
     - "7351"
   healthcheck:
     test: ["CMD", "curl", "-f", "http://localhost:7350/"]
     interval: 10s
     timeout: 5s
     retries: 5
   links:
     - "cockroachdb:db"
   ports:
     - "7349:7349"
     - "7350:7350"
     - "7351:7351"
   restart: unless-stopped

volumes:
 data:

```

**KEY TAKEAWAY:** (i didn’t know this so anyone starting out might not know either)  
Basically the context: is where your **.go and go.mod and dockerfile is**!!! It’s relative to where you run your docker-compose from. (so navigate from your docker-compose to your module folder, leave the other locations as is as they are related to your docker and not machine)

Make a shell command using this  
`docker-compose -f ./docker-compose.yml up --build nakama`

In your directory with .go and go.mod create a Dockerfile without a type and paste this

```auto
FROM heroiclabs/nakama-pluginbuilder:2.12.0 AS builder

ENV GO111MODULE on
ENV CGO_ENABLED 1

WORKDIR /backend
COPY . .

RUN go mod download

RUN go build --trimpath --buildmode=plugin -o ./backend.so

FROM heroiclabs/nakama:2.12.0

COPY --from=builder /backend/backend.so /nakama/data/modules

```

If you’re more experienced this probably won’t help you much, but if you’re getting started I think that just following and copy pasting what I wrote can get you up and running in no time! (definitely less than it took me)

---

<div class="post-metadata">

**Author:** ![Siliyid](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/siliyid/32/413_2.png) [@Siliyid](https://forum.heroiclabs.com/u/Siliyid)\
**Post date:** [December 3, 2020, 2:31pm UTC](https://forum.heroiclabs.com/t/how-to-simplify-and-speed-up-the-golang-module-development/796/5 "2020-12-03T14:31:07Z")

</div>

Thank you for providing this guide, I’m new to Golang and happy to find any useful information.  
I also read this [article](https://yalantis.com/blog/go-application-performance-monitoring/), it’s about how performance monitoring in Golang can be conducted and how to make changes that will affect overall performance.

Long story short, they started the profiler:  
defer profile.Start(profile.MemProfileRate(1), profile.ProfilePath(".")).Stop()  
profile.MemProfileRate(1)` configure profiler to collect information about each allocation.

Then they started the service to make a single request, analyzed appeared mem.pprof file with the command go tool pprof mem.pprof. Next they went command top main:

```
Active filters:
   focus=main
Showing nodes accounting for 6MB, 97.61% of 6.15MB total:
Dropped 51 nodes (cum <= 0.03MB)
      flat flat% sum% cum cum%
       6MB 97.61% 97.61% 6MB 97.61% bytes.makeSlice
         0 0% 97.61% 6MB 97.61% bytes.(*Buffer).ReadFrom
         0 0% 97.61% 6MB 97.61% bytes.(*Buffer).grow
         0 0% 97.61% 6MB 97.61% io/ioutil.ReadAll
         0 0% 97.61% 6MB 97.61% io/ioutil.readAll
         0 0% 97.61% 6MB 97.61% main.main.func1
         0 0% 97.61% 6MB 97.61% net/http.(*ServeMux).ServeHTTP
         0 0% 97.61% 6MB 97.61% net/http.(*conn).serve
         0 0% 97.61% 6MB 97.61% net/http.HandlerFunc.ServeHTTP
         0 0% 97.61% 6MB 97.61% net/http.serverHandler.ServeHTTP

```

After that they run command list main.main.func1 to see the allocation per line:

```
Total: 6.15MB
ROUTINE ======================== main.main.func1 in /Users/user/go/src/article/main.go
         0 6MB (flat, cum) 97.61% of Total
         . . 30:
         . . 31:func main() {
         . . 32: defer profile.Start(profile.MemProfileRate(1), profile.ProfilePath(".")).Stop()
         . . 33:
         . . 34: http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
         . 6MB 35: bb, _ := ioutil.ReadAll(r.Body)
         . . 36: rbody := bytes.NewReader(bb)
         . . 37: n, _ := countLetters(rbody)
         . . 38: _, _ = fmt.Fprint(w, n)
         . . 39: })
         . . 40:

```

As it turned out, the line 35 is reading the whole body of requests, instead of just reading characters (counting characters is the function of the service). So they replaced lines 35 and 36 with rbody := bufio.NewReader(bb). It provided Reader, that is going to optimize performance:

```
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    rbody := bufio.NewReader(r.Body)
    n, _ := countLetters(rbody)
    _, _ = fmt.Fprint(w, n)
})

```

Thus, resource consumption was significantly reduced, with only several actions made.

A great example of how important performance monitoring can be.

---

<div class="post-metadata">

**Author:** ![novabyte](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/novabyte/32/1324_2.png) [@novabyte](https://forum.heroiclabs.com/u/novabyte)\
**Post date:** [December 3, 2020, 3:15pm UTC](https://forum.heroiclabs.com/t/how-to-simplify-and-speed-up-the-golang-module-development/796/6 "2020-12-03T15:15:49Z")

</div>

@Siliyid Nice notes, but just to be clear this is test code you’ve put together and not related to Nakama server. 🙂
