Pointers, Marshalling, and Unmarshalling Data in Go

martin cartledge
Jul 15 · 7 min read
Image for post
Image for post

This is the ninth entry of my weekly series Learning Go. Last week I covered How to Write a Recursive Function in Go. This week I am going to talk about Pointers, JSON Marshal and Unmarshal.

Pointers

Although I have heard of pointers in the past, due to coming from JavaScript, this was a completely new territory for me. To define a pointer as simply as I can, a pointer:

“points” to a location in memory where a value is stored

Sounds fairly semantic, right? I have a feeling most would infer this from the word itself; however, there is much more to what a pointer is. Before I jump into using a pointer in Go, let me explain a few important pieces of pointer syntax in Go.

In Go, there are two operators you need to remember when working with pointers:

& ←- this operator generates an address of the value in memory (generates a pointer)

* ←- this operator allows you to retrieve the underlying value of the pointer

Note: this is commonly referred to as “Dereferencing”

Let’s see an example of both of these operators in action, we will start with the & operator:

We have created our first pointer!

Let’s walk through what is happening here, step-by-step:

inside of func main we declare a variable with the identifier name with a value of martin of type string

next, using the fmt package, we print out the address of the value in memory for name

this outputs the following address: 0xc000010200

This might not seem super useful right now, but let me show you how you can use this address to retrieve a value:

Let me walk through what is happening here, line-by-line:

first, we declare a new variable with an identifier of name with a value of martin of type string

next, we declare a new variable with an identifier of namePointer with a value of a pointer to the name variable

when we print out the value of namePointer on the next line, we receive this address 0xc000010200

next, we declare a new variable with an identifier of underlyingValue, notice we are using the * operator, this allows us to get the underlying value of a pointer value; therefore, the value of underlyingValue is the underlying value of namePointer

we print out the value of underlyingValue on the next line and we see that it’s value is martin

Pretty cool, huh?

Pointers allow us to store references to data at a low level, their address in memory.

JSON

JSON (JavaScript Object Notation) is a widely used format for sending and receiving data in a wide variety of applications. In Go, it is common practice to use two methods when sending JSON and receiving JSON, Marshal and Unmarshal.

Like most things in the Go ecosystem, these functions are named very semantically. Let’s look at the definition of Marshal and Unmarshal.

Marshal — the process of transforming memory representation of an object to a data format for storage or transmission. This is typically used when data must be moved between different parts of an application.

Essentially, when you use the Marshal function on data commonly referred to as Marshalling, you are transforming your data into a format that is better suited for storage or for being transmitted to somewhere else in your application.

Unmarshal — the process of transforming a representation of an object that was used for storage or transmission to a representation of the object that is executable

Since it is common practice to Marshal your JSON data, you can use the Unmarshal function to transform this data into an executable format (a format you can use in your application).

You can read more about Marshalling and Unmarshalling here.

Let me show you a few examples of using Marshal and Unmarshal.

Marshal

Let me walk you through what is happening here:

Inside of package main we are now importing the encoding/json package, this allows us to use the json package

Next, we create our own type with the identifier person of type struct

We give our person type three fields: First of type string, Last of type String, and Age of type int

Inside of our func main, using the short declaration operator, we create a new variable with the identifier me

To assign a value to me, we use a composite literal of type person

Inside of our composite literal, we assign values to each respective field in our person type: First -> martin, Last -> cartledge, and Age -> 29

Next, we create another variable using the short declaration operator with the identifier bff

The value of bff is also of type person

The values assigned for each respective field for our person type inside of this composite literal is: First -> mikel, Last -> howarth, and Age -> 29

Next, we create a new variable using the short declaration operator with the identifier friends

The value of friends will be a slice of type person, we pass the values of me and bff into our composite literal

using the fmt package, we print the value of friends

Quick Note: there are two return values when json.Marshal is invoked:

1 ) a result

2 ) an error

result is a slice of type byte ([]byte)

error is an error

For this example, I gave the result the identifier res, and the error the identifier err

I pass in friends as the single argument to json.Marshal(), keep in mind that friends is a slice of type person

Quick Note: checking for errors immediately after using Marshal or Unmarshal is considered best practice, this prevents any errors or inconsistencies in your data from trickling into your code

Next, we check if the value of err is not nil, if this evaluates to true we step inside of this if statement and our error handling code is ran

For this example, we have no errors so the execution of our code continues

The last line in func main uses the fmt package and logs the value of res, our newly marshaled data

This is the value of res post-marshal:

As you can see, we have a slice of values of type byte, pretty cool!

Unmarshal

Let me walk you through what is happening here:

You will notice that we are importing the encoding/json package just like we did in our previous example, we need the json package to use Marshal and Unmarshal

We are also creating a new custom type with the identifier person with three fields: First of type string, Last of type string, and Age of type int

Using the short declaration operator, I created a new variable with the identifier rawData and assigned it to a slice of person values represented in a JSON string

On the next line, using the fmt package, we print out the value of rawData

Next, using the short declaration operator, we declare a new variable with the identifier byteString, any idea of what we might be doing next?

That’s right, we are setting the value of byteString to a slice of values of type byte. This line is complete once we pass the rawData value into our composite literal

Using the fmt package, we print out the value of byteString

Using the var keyword, we create a new variable with the identifier people that will be a slice of values of type person (our custom type we created)

This is where it gets interesting. Notice that we are assigning only one return value? That is because json.Unmarshal() takes two arguments, the value you would like to Unmarshal or decode, and a pointer (address in memory) of the variable you would like to assign the Unmarshalled data to.

Following common convention, next, we immediately check for an error, if we have one we print that error out

Note: depending on your application and the actions you take after you Unmarshal, you might want to stop all execution. I will talk about this in the future post

Using the fmt package, we print out the value of people. Look at that! Our data is in the same shape as how we started, very cool.

For the sake of using our custom type person to the fullest, I want to iterate over our newly Unmarshalled data and print out their values

Above, we are using the for keyword to create a for statement

This for loop will return two values, an index and a value for each iteration, we assign these values to the variables i and v respectively

Inside of the for loop, using the fmt package, we print out the value of i (index), on the next line we print out the value of each field in our person type: First, Last, and Age

Above is our result, pretty cool huh?

In Summary

Go makes creating and reading memory addresses (Pointers), encoding data (json.Marshal), and decoding data (json.Unmarshal) a painless endeavor. Passing data throughout your application is made easier and more performant with the help of these features of the Go programming language. I hope you enjoyed learning about these features, and if you were already familiar with them, I hope you walked away learning something new about them. Next week I will be talking about Sorting Data in Go. See you then, and thanks for reading!

Dev Genius

Coding, Tutorials, News, UX, UI and much more related to development

Sign up for Best Stories

By Dev Genius

The best stories sent monthly to your email. Take a look

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

martin cartledge

Written by

https://linktr.ee/spindriftboi he/him

Dev Genius

Coding, Tutorials, News, UX, UI and much more related to development

martin cartledge

Written by

https://linktr.ee/spindriftboi he/him

Dev Genius

Coding, Tutorials, News, UX, UI and much more related to development

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store