Golang Data Structures Chapter 5.2

Golang Data Structures Chapter 5.2

golang data structures chapter 5.2

 

Data Structures

As we have explored major Data Structures in Part I of  Fifth Chapter,  let’s dive deeper in Part II –

JSON –

JSON(JavaScript Object Notation) is simple text-based data interchanging format. Basically, we use structs for JSON for putting and receiving the data. It is lightweight and gives a faster performance to access the data

Encoding –

  • Marshal → to encode GO values to JSON in string format

  • Unmarshal → to decode JSON data to GO values

  • Encoding → same as Marshal but in streams

  • Decoding → same as unmarshal but from streams

Go has built-in support for JSON encoding by providing functions in “json/encoding” package.

Marshalling

Marshalling converts the Golang object to JSON encoding into strings. Golang has provided marshal( ) function for this –

Marshalling

 

This function will convert the given data structure into JSON in [ ]byte format which we need to convert into string.

Example – Given data structure Person

data structure person example

 

Create an instance of Person                           

per:=Person{“George”,”United Kingdom”,25}

Now, we can marshal encoded JSON using marshal( ) function.But dont forget to import the “encoding/json” package.

´B,err := json.Marshal(per)

           

If marshalling happens, then err will be nil and b will be [ ] byte containing JSON data like below.

                                   

b==[ ]byte {`{“Name”:”George”,”Address”:”United Kingdom”}`}

           

Here, as per above struct age field will not come because it is not exported which is mandatory for all fields.

Now, we need to convert this [ ]byte to string. So do the type casting

                               

string(b)

       

Now, JSON will be like {“Name”:”George”,”Address”:”United Kingdom”}

Points:

  • All fields should start with the capital letter so that they will be exported

  • JSON objects only support strings as keys; if you want to encode map

  • type to JSON then it must be in map[string] T

  • There is no way for encoding of channels, function types into JSON

  • Cyclic data structures are not supported

  • Pointers are dereferenced before encoded into JSON

Unmarshalling

Unmarshalling converts the JSON data to GO objects. Golang has provided unmarshal( ) function for this –

                                   

func Unmarshal(data [ ]byte,v interface{ })

                   

Here, we specify JSON text as a string and converts into [ ]byte slice

Now, first create the place of that struct type where decoded data will be stored.

                               

var per Person

       

Now call json.Unmarshal( ) by passing it a []byte of JSON data and a pointer to per.

                                       

err:=json.Unmarshal(b,&per)

 

If the JSON fits and matches with struct fields, after the call err will be nil and data from b will have been stored in the struct m, but non-matched fields will not be decoded

String keys in JSON must be matched to struct fields.

Tags

The tags are given to the fields to attach meta information and acquired by using reflection. It is used to provide info on how struct field is encoded to or decoded from another format (or stored /retrieved from the database), but you can use it to store whatever meta-info you want either for another package or for your use.

As we see in the documentation of reflecting. StructTag, by convention the value of a tag string is a space-separated key:”value” pairs,

Example –

Tags

 

If you want to send some field value empty then write omitempty flag in order to let JSON parser know.

 

omitempty

 

With omitempty JSON value will be { }

We can use reflection(reflect package) to access the tag values of struct fields. We need to acquire the type of struct and then we can give query to fields e.g. Type.Field(i int) / Type.FieldbyName(name string)

This will return value of struct field.

The commonly used tag keys are →

  • json → used by json.encoding package, detailed at json.Marshal()

  • xml → used by encoding/xml, detailed at xml.Marshal()

  • yaml → used by gopkg.in/yaml.v2 package, at yaml.Marshal()

  • bson→ used by gobson package, detailed at bson.Marshal()

  • Other – orm, db, gorm, datastore, schema, asn

 

 

Tags

 

Encoding

Encoding works with writer and writing streams of JSON data. The GO has provided below function for encoding JSON through writer interface –                               

func (enc *Encoder) Encode (v interface{ }) error

   

If we see the source code, the NewEncoder(w *io.Writer) *Encoder takes the writer and returns the pointer to an Encoder for encoding and os.Stdout is open file pointing to standard input. Stdout is a pointer to file and a pointer to a file implements func(f *file ) Write(b [ ]byte) (n int, err error) and that means it is implementing this method from Writer interface. (Polymorphism)

Encoding
Encoding

 

Decoding

Decoding works with reader and reading streams of JSON data. The GO has provided below function for encoding JSON through writer interface –                           

func (dec *Decoder) Decode (v interface{ }) error

           

       

NewReader( ) will return a reader and give it to NewDecoder( ) so that it will decode the JSON.                                       

json.NewDecoder(reader).Decode(&p1)

New decoder()

 

Strings –

Golang’s standard library has provided built-in functions to deal with strings in the “strings” package.

Computer” → This string has 8 runes. So no need of counting for finding its length as there is built-in function len( ) for calculating its length.

In Golang, we use len( ) for slice, array, map for measuring their length. So this makes the language more clear and understandable.

strings

 

Interface

An interface is an abstract type. It doesn’t expose the representation or internal structure of its values, or set of basic operation they support; it reveals only some of their methods. When you have a value of an interface type, you don’t know only what it is; you only know what it can do.

Interfaces have named a collection of method signatures only (like java). To implement interfaces in Go, we need to implement all the methods of that interface.

Like a struct, we can create an interface by specifying type keyword followed by its name and keyword interface that will contain methods.

interface

 

Example –

interface

 

Now anything that has the same method signature implements interface like –

interface

 

In above sample example, area( ) associated with square struct has the same signature like shape interface area( ) that means shape interface is implemented by square struct.

See the below example,

interface
interface

 

This is what we call Polymorphism. Polymorphism is an ability to write code that takes on different behavior through its implementation of types.

When you are passing an interface value, then there is no guarantee whether interface type is or isn’t a pointer. In the above example, we created a function based on value receiver and we passed associated values of square or circle to it.

Just take method with pointer receiver.                       

func (c *Circle) Area() float64 {}

Now if we try to pass interface value to it, it will give an error

A circle does not implement Shape(Area method requires pointer receiver). So for the pointer receivers, we need to pass the *Circle pointer to the Shape instead of a Circle value, by using new(Circle) or &Circle.

Remember :

Table

 

Interfaces are types that just declare the behavior. This behavior is never implemented by interface directly, but instead by user-defined types; values of user-defined type can be assigned to values & interface type. This assignment stores values of user-defined type into interface value. – Bill Kenedy

Interfaces can also be used as fields.

interface

 

If you see “bufio” and “ioutil” package in Go’s language specification, you’ll get something like this –               

func NewScanner(r io.Reader) *Scanner

           

→ bufio.NewScanner(res.Body)

           

→ In the Body interface, ReadCloser interface is implemented which again implements Reader interface that means Indirectly we are dealing with the Reader.                   

func ReadAll(r io.Reader) ([]byte, error)

 

→ Same as above

func NewReader(rd io.Reader) *Reader

We need to define meaningful name & type for fields or properties. We can initialize fields with its value or can keep blank so it will use a default value.

In other languages (like Java), we have to explicitly say that this interface is implemented by other. But in Go interfaces are implemented implicitly so you don’t need to say that you just need to use the correct method signature to use from the interface.

interface

 

A type satisfies an interface if it possesses all methods that interface requires. Conceptually, value of interface type or interface value has two components – A concrete type and concrete value.

Sort Package

type Interface

“Sort” package has an interface called type Interface. Sort package provides sorting of any sequence according to ordering function. Go’s Sort function assumes nothing about the representation of the sequence. Instead, it uses sort.interface for specifying sorting sequence and sorting algorithm.

An in-place algorithm needs 3 things – the length of sequence for comparing two elements and way to swap two elements- so it contains 3 methods.

Sort Package

 

So if you want to use sorting then we need to implement these methods from sort.Interface package and then apply Sort( ) on it.

Package sort provided primitives for sorting slices and user-defined collection.

Package sort

 

Empty Interface –

Empty interface has zero methods. It is like Object class (which is a superclass of all classes in java and accept any object). Similar to this, empty interface accepts any interface to itself.

An empty interface can hold any hold values of any type.

Empty interfaces are used by code that handles values of any type.

For example, fmt.Println(a …interface{ }) (n int,err error) takes any type number of arguments of type interface{ }.

empty interface

 

Conversion vs Assertion –

Conversion is converting to one type from another type like int to float. An assertion is different from conversion.

Conversion process deals with two concepts like –

  • Widening → Converting from Lower to Higher data type

  • Narrowing → Converting from Higher to Lower data type

Example –

conversion vs assertion
conversion & assertion

 

Now come to assertion, sometimes you want to know the exact type of interface variable, in this case you have to use type assertion.                           

interface_variable.(type)

interface variable

 

O/P: 10

But here, if we put v.(string) then we will get running panic error

panic: interface conversion: interface {} is int, not string

goroutine 1 [running]:

main.display(0x497e00, 0xc0420361c0)

For this, assertion actually returns the boolean value to tell whether this operation holds or not

assertion returns boolean value

 

O/P: Value is not string

This time o/p will be “value is not the string” instead of getting a panic error. We can also use type switch

As we have seen ‘Data Structures’ in this chapter, let’s move to the next one and see Concurrency in Golang Project

Still-wondering-how-to-find-the-best-Golang-experts-for-your-crucial-project

Comments are closed.