Hello , We are a group a Linux System Administrators with knowledge on Linux, VmWare ,Storage , Bash and we love to learn new things and we love sharing what we know.
Notes: GoLang - Maps vs Slices and Using Slice as buffer
Maps vs Slices
In go maps are refernce oriented. If you pass a map to a function as argument, any changes to that map inside the function will reflect to original function as well.
package main
import("fmt")funcmain(){var testMap =make(map[string]string)
testMap["lang"]="go"
fmt.Println("Before updating the map")
fmt.Println("-------------")for key, val :=range testMap {
fmt.Println(key, val)}_=updateMap(testMap)
fmt.Println()
fmt.Println("Before updating the map in another function")
fmt.Println("-------------")for key, val :=range testMap {
fmt.Println(key, val)}}funcupdateMap(testMap map[string]string)map[string]string{
testMap["type"]="compiled"return testMap
}
The main reason behind this is, in Go maps are implemented as pointer to structs
Passing a map to function means that you are copying a pointer i.e address/reference of the map, so any changes to map will happen at the memory of the map.
While designing APIs, having maps as input or return values is bad choice due to we dont what that map contained.
As you pass the map and these are something similar to updated by reference, in any where of your code, if you update the map, there is no of knowing unless we inspect the code.
So during the cases where map implementation needed, we can leverage struct, as to struct update will not have any thing like reference, so you must return the struct to know the changes
package main
import("fmt")type Student struct{
name string
num int}funcmain(){
s := Student{"student1",111}
fmt.Println(s.name)
newName :="student2"// case 1 not caputering it_=updateStudentName(newName, s)
fmt.Println(s.name)// case 2 caputering it
s =updateStudentName("Student3", s)
fmt.Println(s.name)}funcupdateStudentName(newName string, s Student) Student {
s.name = newName
return s
}
When it come to slices, they are updated by reference at one case and they are not yet another.
To put it in simple words, under criteria of length and capacity, if you update a slice and its copy as long as it maintaines the same memory location pointer, both will get updated.
but if some append operation which might change length of slice, then Go runtime will try to use existing slice capacity else create a new memory location and thats where the break will happen with orignial slice and new slice in terms of memory location.
if go trying to use existing slice reserved capacity, then it will be a shared scenario. Slice1 and Slice2 will share what ever the data common and new data appended to slice2 will be hidden from slice1, and length of slice1 also will not change.
package main
import("fmt")funcmain(){
slice1 :=make([]int,5,5)
slice1 =[]int{1,2,3,4,5}
fmt.Println(slice1)
slice2 := slice1
fmt.Println(slice2)// update by changing existing
slice2[0]=100
fmt.Println(slice1)
fmt.Println(slice2)// now do append
slice2 =append(slice2,101)
fmt.Println(slice2)
fmt.Println(slice1)}
Slices As Buffers
So as long as you replace data to slice, it size and length wont get change.
so the memory location wont change
every time old data processing completed, new data get placed into the same memory location.
so garbage collection is only once and that is the end of the complete Read operation.
to read from file, we create the famous byte buffer and every time read the chunk of byte from the sources
then process it
data :=make([]byte,100)
count, err := file.Read(data)// count is length of chunk that we read// err returns if any
0 comments:
Post a Comment