Learn back-end development by writing real code

Boot.dev Blog ยป Golang ยป Golang Conversions - Ints to Strings and Strong Typing

Golang Conversions - Ints To Strings And Strong Typing

By Lane Wagner on Mar 31, 2020

Curated backend podcasts, videos and articles. All free.

If you're looking to become a backend developer, or just stay up-to-date with the latest backend technologies and trends, you found the right place. Subscribe below to get a copy of our newsletter, The Boot.dev Beat, each month in your inbox. No spam, no sponsors, totally free.

Go is a strongly typed language, which means at any point a developer should know exactly what type of value they are dealing with. For example, if we have a function that prints a string, we can’t just give it an integer and expect it to work. We have to cast it to a string explicitly:

func main() {
	num := 5
	numString := strconv.Itoa(num)

func printString(s string) {

If we don’t cast the value, the go compiler won’t even let us compile the program.

๐Ÿ”— Dynamic Typing is Slow

Developers coming from dynamically typed languages often get annoyed with Go’s strong typing. They think that the compiler should just know what they mean and do the type cast implicitly. Strongly typed languages won’t guess for you. They make you make the decisions.

There is a reason for this. Type conversions take time and resources. If the Go runtime were to dynamically type every value then programs would run a lot slower in general. If you want slow programs then go back to Python or Javascript.

๐Ÿ”— Strong Typing Is Explicit

In addition to strong typing being faster, strong typing allows the developer to know exactly what type of value they are dealing with. I can’t tell you how many times in Python I’ve had to run a program and print out what type of object something is. (Looking at you NumPy)

๐Ÿ”— Strong Typing Saves Memory

red floppy disk

In one of our production apps, we were storing millions of ints in memory. Being on 64-bit machines, this means that we were storing 64 bits for each integer when in reality the integer stored was never greater than 10. By swapping out ints for uint8s we saved 80% of the memory that our application was using. The guy paying our cloud bill was quite happy about that.

While changing int and float types can save memory, beware of these kinds of optimizations. A program can become quite hard to read if every other line is:

toRound := float64(someNumber)
toSave := float32(toRound)

The truth is that most of the standard library functions and popular packages (and hopefully the stuff you write too) uses “default” sizes. For example, math.Round uses float64s and time.AddDate uses ints. Unless the memory savings are significant, it’s usually best to stick with “normal”.

๐Ÿ”— Interfaces - Not Duck Types

Interfaces allow for a kind of polymorphism in Go. Their purpose is not to give developers a way to sneak dynamic typing into the language. I’ve seen developers do things like:

func jsonToDynamic(dat []byte) {
	m := map[string]interface{}{}
	json.Unmarshal(dat, &m)
	// do something with m["hello"]

I humbly ask… why? When unmarshalling JSON, 99% of the time we should know the shape of the object. If we know the shape of the object, then we should unmarshal into a struct where each field’s type is declared. We will even get a nice unmarshal error if the shape is malformed.

Find a problem with this article?

Report an issue on GitHub