Cannot assign to struct field in map

Understanding Maps in Go

Have you ever come across an error “Cannot assign to struct field in map”? So what is the issue here?

Imagine that we have a structure:

package main

type Product struct {
	Name  string
	Image string
	Cdn   string
	Price float64
}

func main() {

	products := make(map[int]Product)

	products[0] = Product{"Blue Diamond Book", "https://localhost/split/bdb.png", "https://localhostcdn/split/bdb.png", 120.00}
	// Problem
	products[0].Price = 121.00

}

The Error

If we have to reassign value to a variable like this:

products[0].Price = 121.00

We’ll get an error: “Cannot assign to struct field in map”

Pointer Map Problem in Golang

The reason for this panic is, the map is a pointer to value and Go checks the key, is it there or not. If you had used a map, you must have seen:

thisProduct, ok := products[0]

thisProduct” will get the Product structure’s object and “ok” will get a bool value, that this key exists or not

So we have to assign the pointer to a variable.

// Solution
	if thisProduct, ok := products[0]; ok {
		thisProduct.Price = 121.00
		products[0] = thisProduct
	}

Now, we can access and reassign the value of the Student structure’s object:
thisProduct.Price = 121.00
After making the required adjustments, this thisProduct can be assigned back to the same pointer.

Worth Sharing?

How to use SSL with OCSP with GIN Framework in Go

The GIN framework comes up with the SSL middleware autotls which requests the SSL certificate on request basis. However, it lacks the cool feature of OCSP

However, the CertMagic which generates SSL certificate during initializations – so no surprises here and does support OCSP.


app := gin.Default()
...

// Assuming SSL_DOMAIN has csv domains like varunbatra.com,www.varunbatra.com
domains := os.Getenv("SSL_DOMAIN")
domainsMap := strings.Split(domains, ",")
err := certmagic.HTTPS(domainsMap, app)
if err != nil {
	log.Fatal(err)
}

Worth Sharing?

Containerize your first Go Lang App using Docker

Does size matter?

It does – in production. Most orchestration solutions involve a smoother transitions from one docker image to other. A simple up command, if downloading only ~10MB of file, obviously it will save few seconds – but not just that, what about limited size we have in our production servers? This normally leads to the regular cleanups which is usually a manual and tedious tasks. So, for a scalability point of view, a multi-stage build approach is preferred over usual.

The Multi stage build Approach

Most of the approaches are quite poor as it ends up with a large docker image. New approach involves having a two steps approach as following:

The Build:

You build Go in this system and use that to build your application. This will result in an insane size of docker image ~ from 200MB to 300MB

Copy Build

You copy the build from first step and this ensures size of final docker image is less. I bet you will have no more than 10MB image size.

Example:

# The Build
FROM golang:alpine AS the-build
ADD . /src
RUN cd /src && go build -o app

# Copy Build
FROM alpine
WORKDIR /app
COPY --from=the-build /src/app /app/
ENTRYPOINT ./app

Here you are naming the first step of the build as ‘the-build’ Docker supports a partial build on multi-build process. So if you would like to build till ‘the-build’ you can do it with:

docker build --target the-build -t github/go-app:latest

If you omit –target – you can build the whole system in a single command as following:

docker build -t github/go-app:latest

Worth Sharing?