As we have seen how control flow and functions work in Chapter – 4 of our Golang tutorial, let’s have a look at major Golang Data Structures.
Well, almost every programmer knows what is an array. But let’s revisit the concept one more time –
Basically, an array is a number of elements of the same type stored in sequential order. We use arrays to store fixed no. of more elements which is really a good data structure.
We need to follow the below syntax to create an array :
var var_name [size]var_type
Example –
var arr [10]int //It will create an array with name”arr” of 10 integers
Learn about Golang fundamentals here as a starting point.
func main(){ var x [5]int x[3] = 1000 fmt.Println(x) b:=[5]int {54,76,34,2,3,} /*we have initialized this array and notice extra trailing , after last element of array which is required in Go. we no need to specify type because Go can figure it out */ }
main.go package main import ( "fmt" ) func main() { var name [50]string //array of 50 string elements fmt.Println(name) name[43] = "Welcome to Go Programming" fmt.Println(name) var x [100]string fmt.Println("Length of arr x:", len(x)) //calculate length of array z := [5]int{43, 78, 54, 23, 22} fmt.Println(z) for i := 65; i <= 122; i++ { x[i-65] = string(i) } fmt.Println(x) }
Slice is the same as an array but it has a variable length so we don’t need to specify the length to it. It will grow whenever it exceeds its size. Like an array, slice also has index and length but its length can be changed.
Syntax for slice creation is:
var var_name [ ]var_type
The only difference between slice and array is that there is no need to specify length while creating a slice.
var x[ ] float64
Here, a slice of type float64 elements will be created with length 0 & capacity 0
func main() { nums:=[ ]int {5,7,4,8,9} //No need to specify length fmt.Println(nums) }
We can also create slice by using make() also which is available in builtin package of golang
func make(Type,size IntegerType)Type x:=make([ ]string,5) → Here the capacity of slice equal to length of it
This will create a slice of underlying string array having a size for 5 elements
Length→ No. of elements present
Capacity→ Total Size
The length and capacity of a slice can be obtained by using len(slice), cap(slice)
Below is another example –
array:=[ ]float64 {1,2,3,4,5} //slice of float64 elements x:=array[0:5] fmt.Println(x)
Normally we switch the ON value of a variable but Golang control allows you to switch ON type also.
var a [10]int → equivalent as a[0:10], a[:10], a[0:], a[:]
Remember → String is made up of runes (Uni Code). A rune is Unicode UTF Code point (for ‘A’-65’, ‘a-97’). A Unicode code point is 1 to 4 bytes.
So, strings are made up of runes, runes are made up of bytes, so strings are made up of bytes. A string is a bunch of bytes, a slice of bytes.
You can access slice elements by using a range-in for a loop.
There are built-in functions to calculate length by using len(slice), capacity by using cap(slice), append one slice to another by using append(slice) and copy(slice) to copy one slice to another.
We can create a slice in three ways:
func main() { elements := []int{3, 5, 2, 6, 2} arrays := make([ ]int, 0, 3) //Creating slice with make( ) for n := range elements { fmt.Println("Elements", n) } for i := 0; i < 80; i++ { arrays = append(arrays, i) // to append i elements to slice fmt.Println("Len:", len(arrays), "Capacity:", cap(arrays), "Value: ", arrays[i]) }}
Here in the above program, you can see how length and capacity increase when it exceeds size limits. The capacity will be doubled when the size exceeds the capacity.
If we think that our slice might grow, we can set capacity which is larger than length. This gives the slice room to grow without creating a new array every time our slice grows.
We also can create slice inside another slice like –
sliceOne:=make([ ][ ]int,0) //slice of slice of int
main.go package main import ( "fmt" ) func main() { primes := []int{1, 3, 5, 7, 9, 11} fmt.Printf("%T\n", primes) //type []int fmt.Println(primes) //[1 3 5 7 9 11] fmt.Println(primes[2:4]) // [5 7] 3rd 4th element var info []byte //Slice using var elements := []int{3, 5, 2, 6, 2} //Slice using shorthand notation arrays := make([]int, 0, 3) //Creating slice with make( ) //String slice str := []string{"Amazing", "Brilliant", "Good One", "Excellent"} for n := range elements { fmt.Println("Elements", n) } for i := 0; i < 80; i++ { arrays = append(arrays, i) //append i elements to arrays fmt.Println("Len:", len(arrays), "Capacity:", cap(arrays), "Value: ", arrays[i]) } fmt.Println("Info elements:", info) for i, vals := range str { fmt.Println("Values", i, vals) } //Slice of Slice OutIn := make([][]int, 0, 3) for i := 0; i < 3; i++ { out := make([]int, 0, 4) for j := 0; j < 4; j++ { out = append(out, j) } OutIn = append(OutIn, out) } fmt.Println(OutIn) }
One of the most important and useful data structure in computer science is the Hash Table. Golang provides a map data structure that implements hashtable. A unique key-value pair like a dictionary is used to look up values based on the key.
map [keyType] valueType
var dictionary map[string]int //map using var dictionary[“Zero”]=1 fmt.Println(dictionary[“Zero”]) //Accessing value using key
Here map name is dictionary having key-value pairs of string & int type.
The values are accessed using key values. The maps can be created by using make( ) also which is more effective to use.
dictionary:=make(map[string]int) //map using make()
The make() creates a hash data structure and return map value pointed by key. Go provides familiar syntax to work with a map data structure.
The functions provided are len(map) and delete(mapName,key)
func main(){ var details = map[int]string{101: "Jordan", 102: "Roger", 103: "Rafel"} //using var fmt.Println(details) fmt.Println(details[102]) countries := make(map[string]string) //Shorthand and make countries["US"] = "United States" countries["IND"] = "India" fmt.Println(countries) }
Comma OK idiom: If we are looking for value related to a particular key then map returns two values: one value if found and value that indicates success or failure(not present). We call this comma OK idiom.
func main(){ countries := make(map[string]string) countries["US"] = "United States" countries["IND"] = "India" if val,ok:=countries[“IND”] ; ok{ //comma ok idiom fmt.Println(“Value”,val,”is present”) fmt.Println(ok) //it will return true as ok is bool type }
Range: Range is used to iterating over the slice and map along with for loop. When a range is used with slice it returns two values- 1st one is an index and 2nd one is a copy of the element at that index.
func main(){ countries := make(map[string]string) countries["US"] = "United States" countries["IND"] = "India" for country, capital := range countries { fmt.Println(country, "-->", capital) } }
main.go package main import ( "fmt" ) func main() { var details = map[int]string{101: "Jordan", 102: "Roger", 103: "Rafel"} fmt.Println(details) fmt.Println(details[102]) //Accessing value based on keys countries := make(map[string]string) //Shorthand and make countries["US"] = "United States" countries["IND"] = "India" countries["UK"] = "United Kingdom" fmt.Println(countries) capitals := map[string]string{ //Shorthand composite literal "India": "Delhi", "US": "Washington"} capitals["UK"] = "Great Britian" //Adding an entry capitals["NZ"] = "Wellington" capitals["UK"] = "London" //Updating entry fmt.Println(capitals, " of length", len(capitals)) //len() for Length delete(capitals, "NZ") //deleting entry fmt.Println(capitals) //Comma OK if value, present := capitals["US"]; present { fmt.Println("Value", value, "is present") fmt.Println("Status:", present) } for country, capital := range countries { fmt.Println(country, "-->", capital) } //map inside map CountryInfo := map[string]map[string]int{ "INDIA": {"IN": 91}, "United States of America": {"US": 1}, //always give the,after last element } for key, val := range CountryInfo { fmt.Println(key, "--->", val) } }
Golang doesn’t have keyword ‘Class’ but it has ‘struct’ which is contains named collection of fields/properties. The struct is also there in ‘C’ language.
In some object-oriented languages, methods are composed within struct or class
Class Animal{ public void eat() { } //Method defined in the class itself }
But in Golang, they are ‘associated’ with struct.
type Animal struct{ } func (e Animal ) eat () { } //Methods defined outside but works on same struct
A struct is defined by using type and struct keyword along with the meaningful name
type House struct { } type Car struct { } type #Mobile struct { } //invalid
Here type defines new type followed by name of struct and then struct keyword
Example –
type Mobile struct { brand string model string price int }
We can create an instance of our struct Mobile in many ways like
var mob Mobile
This will create local variable mob and sets the default value to its fields (0 for int, “ ” for string, 0.0 for float)
mob:=new(Mobile)
It will allocate memory to all fields by setting default values and returning a pointer to it (*Mobile). More often we need to give values to each of the fields. We can do this in two ways:
mob:=Mobile{brand:“Samsung”,model:”Galaxy”,price:24500}
OR
mob:=Mobile {“Samsung,Galaxy,24500”}
We need to define a meaningful name & type for fields or properties. We can initialize fields with its value or can keep blank so it will use the default value.
We have to access the struct fields with “. (dot)” only.
There is no concept like public, private, protected for the visibility purpose in Golang. As Golang is simple, if the first letter of the struct name or variable name is capital then it is visible outside that package.
type Mobile struct{ //this struct can be exported brand string //not exported Model string //exported }
Go supports methods to define a struct.
func (receiverName receiverType) functionName(arguments) returnType
In between the keyword func and functionName, we’ve added the receiver. “Receiver” is like parameter-it has its name and type, and by creating this we have to call the function using “.” operator.
You cannot declare a method with a receiver whose type is defined in another package.
func (mob *Mobile) show () string { //func associated with Mobile mob.brand = "Xiomi" return mob.brand } ………. var mob Mobile fmt.Println(mob.show())
Methods having pointer receivers can modify the value to which the receiver points.
We can define a method on any type defined in struct as well as from same package but you cannot define method on type from another package.
main.go package main import ( "fmt" ) type width int //user defined type type Mobile struct { brand string model string price int } func (mob Mobile) display() string { //func associated with Mobile mob.brand = "Xiomi" return mob.brand } func (mob *Mobile) show() string { //func associated with Mobile mob.brand = "Xiomi" return mob.brand } func main() { var height width fmt.Println(height) m := Mobile{} fmt.Println(m) //Default values inside struct{" " 0} var mob Mobile //Instance creation using var fmt.Println(mob) mobs := new(Mobile) fmt.Println(mobs) phone := Mobile{"Samsung", "Galaxy", 24500} //Struct initialization fmt.Println("Before Change:", phone) fmt.Println("Function Call", phone.display()) // Xiomi fmt.Println("After Change:", phone) //still old values are coming {"Samsung","Galaxy",24500} fmt.Println("Function Call:", phone.show()) //calling show() fmt.Println("After Change:", phone) //Here changed values will reflect }
We can create aliases for the type that you want to use.
main.go package main import (“fmt” “strings”) type s string func (myStr s) Upper() string{ return strings.ToUpper(string(myStr)) } func main(){ fmt.Println(s(“hello”).Upper()) }
We can also attach methods to the types. See the “time” package having type Duration – https://golang.org/pkg/time/#Duration
A struct’s properties/fields usually represent has-a relationship like an inheritance. Suppose we have a struct person.
type Person struct { Name string } func (per *Person) speak () { fmt.Println(“Hello, I’m”,per.Name) }
And now if we want to create a new struct. We can do like this –
type Mobile struct{ Person //Embedded type Model string }
So, Go supports relationships like this by using embedded type, also known as anonymous fields.
Here, we are using type Person by embedding into Mobile. Now to access the struct Person fields we can use type name.
mob:=new(Mobile) mob.Person.speak( )
Embedding is the composition, not inheritance, but Go supports something called “promotion” where the fields and methods of the embedded type become available to the embedding type.
This is something like inheritance but actually not inheritance.
main.go package main import ( "Fmt" ) type Person struct { FirstName string LastName string Age int } func (per *Person) show() { fmt.Println(per.FirstName, "", per.LastName, "", per.Age) } func (cust *Customer) show() { //method overriding based on receiver fmt.Println(cust.ContactNo) } type Customer struct { Person //embedded type ContactNo int } func main() { cust := Customer{ Person: Person{ "John", "Matthew", 25, }, ContactNo: 9965, } cust.Person.show() cust.show() }
Go automatically handles conversion between values and pointers for method calls. You may want to use a pointer receiver type to avoid copying method calls.
We can use struct pointer to access struct fields –
mob:=&Mobile {“Lenovo”,”A6”,”6700”} fmt.Println(mob.brand,mob.model,mob.price)
Well, we have covered some of the major Data Structures for Golang in this chapter. In Part II of this chapter, we will dive deeper and explore some more Golang Data Structures. We as a Golang development company help businesses develop applications. Read more on our Golang Tutorial to learn about efficient practices related to GoLang.
How to Effectively Hire and Manage a Remote Team of Developers.
Download NowMindbowser played a crucial role in helping us bring everything together into a unified, cohesive product. Their commitment to industry-standard coding practices made an enormous difference, allowing developers to seamlessly transition in and out of the project without any confusion....
CEO, MarketsAI
I'm thrilled to be partnering with Mindbowser on our journey with TravelRite. The collaboration has been exceptional, and I’m truly grateful for the dedication and expertise the team has brought to the development process. Their commitment to our mission is...
Founder & CEO, TravelRite
The Mindbowser team's professionalism consistently impressed me. Their commitment to quality shone through in every aspect of the project. They truly went the extra mile, ensuring they understood our needs perfectly and were always willing to invest the time to...
CTO, New Day Therapeutics
I collaborated with Mindbowser for several years on a complex SaaS platform project. They took over a partially completed project and successfully transformed it into a fully functional and robust platform. Throughout the entire process, the quality of their work...
President, E.B. Carlson
Mindbowser and team are professional, talented and very responsive. They got us through a challenging situation with our IOT product successfully. They will be our go to dev team going forward.
Founder, Cascada
Amazing team to work with. Very responsive and very skilled in both front and backend engineering. Looking forward to our next project together.
Co-Founder, Emerge
The team is great to work with. Very professional, on task, and efficient.
Founder, PeriopMD
I can not express enough how pleased we are with the whole team. From the first call and meeting, they took our vision and ran with it. Communication was easy and everyone was flexible to our schedule. I’m excited to...
Founder, Seeke
Mindbowser has truly been foundational in my journey from concept to design and onto that final launch phase.
CEO, KickSnap
We had very close go live timeline and Mindbowser team got us live a month before.
CEO, BuyNow WorldWide
If you want a team of great developers, I recommend them for the next project.
Founder, Teach Reach
Mindbowser built both iOS and Android apps for Mindworks, that have stood the test of time. 5 years later they still function quite beautifully. Their team always met their objectives and I'm very happy with the end result. Thank you!
Founder, Mindworks
Mindbowser has delivered a much better quality product than our previous tech vendors. Our product is stable and passed Well Architected Framework Review from AWS.
CEO, PurpleAnt
I am happy to share that we got USD 10k in cloud credits courtesy of our friends at Mindbowser. Thank you Pravin and Ayush, this means a lot to us.
CTO, Shortlist
Mindbowser is one of the reasons that our app is successful. These guys have been a great team.
Founder & CEO, MangoMirror
Kudos for all your hard work and diligence on the Telehealth platform project. You made it possible.
CEO, ThriveHealth
Mindbowser helped us build an awesome iOS app to bring balance to people’s lives.
CEO, SMILINGMIND
They were a very responsive team! Extremely easy to communicate and work with!
Founder & CEO, TotTech
We’ve had very little-to-no hiccups at all—it’s been a really pleasurable experience.
Co-Founder, TEAM8s
Mindbowser was very helpful with explaining the development process and started quickly on the project.
Executive Director of Product Development, Innovation Lab
The greatest benefit we got from Mindbowser is the expertise. Their team has developed apps in all different industries with all types of social proofs.
Co-Founder, Vesica
Mindbowser is professional, efficient and thorough.
Consultant, XPRIZE
Very committed, they create beautiful apps and are very benevolent. They have brilliant Ideas.
Founder, S.T.A.R.S of Wellness
Mindbowser was great; they listened to us a lot and helped us hone in on the actual idea of the app. They had put together fantastic wireframes for us.
Co-Founder, Flat Earth
Ayush was responsive and paired me with the best team member possible, to complete my complex vision and project. Could not be happier.
Founder, Child Life On Call
The team from Mindbowser stayed on task, asked the right questions, and completed the required tasks in a timely fashion! Strong work team!
CEO, SDOH2Health LLC
Mindbowser was easy to work with and hit the ground running, immediately feeling like part of our team.
CEO, Stealth Startup
Mindbowser was an excellent partner in developing my fitness app. They were patient, attentive, & understood my business needs. The end product exceeded my expectations. Thrilled to share it globally.
Owner, Phalanx
Mindbowser's expertise in tech, process & mobile development made them our choice for our app. The team was dedicated to the process & delivered high-quality features on time. They also gave valuable industry advice. Highly recommend them for app development...
Co-Founder, Fox&Fork