a small team of google
google used three languages
it is a legacy issue when c and cpp was designed computers did not have much memory so they had to be compiled at low memory so compile time was compromised
when python , java and cpp was designed computers had to do one task at a time so there was only one thread but now we need many concurrent things to happen so concurrency was added in later or patched at best . But at the the time of designing GO concurrency was there from the beginning .
…
package main
every programm has to be in a package and main is a special package as its the entry point
import ("fmt")
generric import statement , fmt
is a package for formatting string (usually pronunced as ফমট / fomt )
func main
main function in the main package , ( entry point )
…
var i int
hear var
is keyword for declaration , i
is variable name and int
is variable typevar i int = 43
i:=43
, hear compiler determines what type it is and assigns valuehear i
is a package level variable
a more organized way to decalre multiple variables
ther same variable in the inner scope gets preference this is called SHADOWING , this allows bothe the variable value and type to be changed
{}
) , the variable is never visible outside the blockunassinged bool variable has default value as false
type conversion is not posssible for bool , so no bool -> int or int -> bool possible
int
signed
int8 | -128 to 127 |
int16 | -32786 to 32767 |
int32 | - 2 billion to 2 billion |
int64 | -9 quintillion to 9 quintillion |
if bigger number is needed theres a way in math package to get arbitary big numbers
unsigned
var n uint8 = 43
uint8 | 0 to 255 |
uint16 | 0 to 66535 |
uint32 | 0 to 4 billion |
there are no 64 bit unsigned integer . byte type which is alias of unit8 as it is very "famouse"
sign | operation |
---|---|
+ | add |
- | subtract |
* | multipply |
/ | division |
% | reminder |
cat operate on different type on GO , there are no type coertion like JS , explicit type conversion has to be done in GO
sign | operation |
---|---|
& | and |
| | or |
^ | xor |
float32 | ± 1.18E-38 to ± 3.4E38 |
float64 | ± 2.23E-308 to += 1.8E308 |
bit operator dont work with float
NB. no other language treats complex type as a basic type that why GO is suitable for data science
there are two complex type based on capacity
String is array of utf-8 ( 8 bit )charecters , so it can encode every charecter avaiable thatsw why we need other type (rune) ,
string can be treated as array
byte is an alias of string
ther is psudo arethmetic support for string s1 + s2
byte slicing is needed when sending response to ohter services over the web
in utf-32 any charecter can be 32 bits long but does not have to be 32 bit long . so a valid utf-8 is a valid utf-32 charecter (this is a bit tricky)
or
rune is type alisa of int32 , ther is a built in function named ReadRune
the above code will cause error beacuse const has to be assigned at compile time and the function will execute at runtime
NB. arrays/collections are mutable types by default and they can not be typed constant
const can be shadowed
const is untyped , the compiler simply replaces all a with 10 , so the below code will cause error
iota is used for counter in a scope
ex-1
ex-2
ex-3
ex-4
ex-5
default int value is 0 amd iota starting value is also 0 , this might cause unexpected error
to solve this issue we can initiate iota with error value
ex-6
we can also offset iota like this
ex-7 (example of file size const with iota)
ex-8 (role and permissions implementation with iota)
isAdmin | 1 << iota | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
isHeadquater | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | |
canSeeFinantial | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | |
canSeeAfrica | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | |
canSeeAsia | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | |
canSeeEurope | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | |
canSeeNorthAmerica | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | |
canSeeSouthAfrica | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
method-1
method-2
__NB. empty array value is []
len() function is used to determine array length
array in go are different than other languages , array in go are considered value
in other languages when copying an array we will be using the same data ( passing by reference) but in go when copying another exact copy of the array is made .
so why is this even important to note ?
when passing an array to a function , if the array is really big with millions of data the programm is going to be slowed down as copy by value is going to be occure
to avoid this use
& is called address of operator
b := &a tells compiler b is going to point to the same data as a ( a and b will be pointing to the same data )
the length of an array has to be known at compile time which limits its usefullness , hear slice comes to rescue
len() function is avaiable , cap() shows the capacity of slice
now for slice
a and b are pointing to the same data
hear a , b , c ,d , e are pointing at the same data in different ranges ,
[3:6] hear is [inclusive:exclusive] , will output [4,5,6]
appending a slice
ex-1
ex-2
explanation , we first created slice with 0 elements so go created an empty array , but when we appended 1 it could not fit so go had to create an new array (double is size )and copy all the values there ,
this is ok for a samll slice but as things get big copy operation gets costly ,
to avoid this we can use a suitable value is make functions third parameter , then append function would not need to copy to a new array
append can take two or more arguments
NB. if slice append exceeds the base size of the slice go is going to pow 2 the size of the underlying array 2 -> 4 -> 16
ex-2 (concatinate two slices in go)
above code will not work as we are trying to append two differenct types array and slice
to make this work we have to spread the array
this becomes
ex-3 (implement stack in go)
stack has push and pop functions . push will be done by append and pop can be done by shift operation
ex-4 (remove element from the middel of a slice)
lets assume we want to remove the third element from a slice
we have to be careful as we are working with references as we will ses in the code below
we have to be careful of not using the same reference in other places
example
value for a map can be of any type but to be a key for a map the type has to be testable with euqality
for example string , array , numbers can be tested if they are equal 1 == 1 "arif" == "sarif" , but not slice and map
another way of creating map is make function
NB . the return order of map keys is not gaurenteed
remove entry from a map
default map key value is 0 . not existing key returns 0
so if a map has value as 0 how can we know if the key exists and is 0 or the does not exist thuse the value 0
if key existed ok would be true
how do we know how many elements are there in map
NB. mpas are passed by reference
another collection type
we could also write this as
for this approch order has to be maintained
struct name starting with capital letter will be exported but if the property names are not capitized they wont be visible outside the package
used mostly in short lived use cases
NB. structs are passed by value not reference
to pass reference we can use address of operator (&)
go does not have traditional OOP for example it does not have inharitance but to implement inharitance we can use embaded struct
Go does not support isA relation but supports hasA relation or embaded
we can say a bird has animal like characteristics
but if we use literal syntax
tags just pass a string with property as metadata nothing else
tags are written in the right side of the property with backticks
to retrive tags
basic example
in got we will alwasy have to use brances
logical operator are same as other languages
NB. floating point evaluation has to be do
falling through ,
in other languages we do
but in go there is no falling through instead we have the ability to test multiple test in a single case
if some number is repeted in more then one case it is going to cause an error so the numbers have to be unique
NB. in to break statemetns are implicit , as break tends to cause errors when we forget to write it so go designers made it implicit
fallthrough in go if we put fallthrough keyword after any case the next code is going to execute
hear event if i is 2 the code is i == 1 is going to execute beacuse of fallthrough
NB. i.(type) returns the type of a variable , but only inside switch case controll flow not outside switch
how do we catch [3]ubt{1,2,3} with typed switch in golang
we can break statement explicitly to break out of a switch statement if we want
a simple loop
writing like below will cause error
instead we have to write it like
in the above code increment section if we write i++ and j++ , it would cause error as i++ is not an expression in go it is an statement
NB. expression is something that resolves to a value (returns a value )
while loop substitution with for in go , with only the condition section
this is also valid
NB. break and continue are same as other languages (like c )
there is a concept in golang called label , this can be used to break out of loops
this might seem like c langs goto statement but its not . loop hear indicates from where do we want to break out of.
we can use this format with
only loop through keys
or
only values
_ is a special variable in go which is called the readonly variable and go compiler ignores it
DEFER function invokes a function but delays it execution to some future point in time
PANIC an application can panic , go application can enter a state when it can no longer continue to run and now go runtime trigger that or trigger it on our own
RECOVER when application starts to panic we need to somehow save the application and signal that to the rest of the application
the way defer works hear it it delays the execution of the statement it moves it after the main function but before the main function returns
defer works LIFO (last in first out)
so the last function that gets deffered will be the first to get called
use cases we often use defer keyword to close out resource and it it logical that we close resources out in the opposit order we open them , as resource might be dependent on the other one
NB. defere statement executes after the main function is done but before the main function returns
this example is a sample rpogramm that requests a file from netwok and reads the contents of the file
in the above application defer can help with the body close . As we can seee we closed the file lines later to the request but htere is a prossibility that we might forget to close it later . Hear defer can help us after the request we can close e witha deffered keyword
so code could be like below
NB. the most common use case for using defer allows us to associate opening and closing of reses next to each other
NB. when we are opening a lot of resources say with a loop then using defer might not be the best choice as defer will execute before main returns so milions of resources will stay oen and close all togather at the end . we might explicitly close then after are done delegate resource handelling to another function and let it handel the closing of it
defer takes the value of a variable at the time defer was called
In go there are no Exception
. like most languages what is said to be exceptional like most it go it is quite normal .
lets sat we are trying to open a file that does not exist many languages will consider it as an exception but go will simply return an error value
however there are cases where a Go application can not continue which in go is called panic
Ex
ex
NB.it is very rare that go is going to panic . it would in most cases return a error value its up to use how we handel it
NB.Panics happen after the deffered function are executed
ex
recover function returns nil if application is not panicing else will return error that causes the application to panic
hear we see recover catches the error but our programm still exists . But recover still has impact if we have depper call stack which we will see in the next example
ex
when the panic occurs in the panicker function . the usual execution will stop and execute the derrered function the deffered function recovers the application and the normal excution flow starts again
calling recover means that we are going to deal with what ever is wrong with but in case we cant we can re panic the application
so if we change the code a bit
agenda
ex
ex(pointer arithmetic)
go does not support pointer arithmetic built in. if we must use it we have to use the unsafe
package
P.A was left out of go for simplicity as P.A can get very complicated
ex (how can we create pointer types )
another way to initialize variable to be pointed to an object is
NB.with new we can only create empty objects
dereferencing with pointer
the perenthesis are hear because dereferencing operation ( * ) has lower precidence then the dot (.) operator
without the perenthesis we would be dereferencing (ms.foo ) the whole thing
the above code can also be written as
as go had limits of pointer it can help us out by making syntax easy , this is just syntactic sugar the compiler is helping us out (*ms).foo and ms.foo are same to the compiler hear
ex(why are slice / map copied by reference when assigned to another variable)
beacuse they are a pointer reference to an underlying array
same thing with maps
ex(how to declare pointer of a type)
prefix the type with an asterics of the variable
agenda
ex
function starts with func if function name is upper case it will be exported
if multiple parameters are of the same type we can specity the parameter at once
we can pass parameters as pointer in a function for small values it might not matter much but for large data structures passing by pointer is efficient as the value need to be copied every single time
But passing maps and slices to a function is always as a pointer
when passing variable parameter we can only pass one and it has to be the last one
NB. a rare feature that go has that other languages do not is go can return a loal variable as a pointer
it is rare beacuse when we declare the
sum
variable we decalre it in the execution stack of this function which is a special section of the memory which is set aside for all the operation this function is going to be working with . when this function exits that execution stack is destroyed and memory is freed up
but he pointer would be pointing to a blank location with garbage value but in go lang when it realizes we are returning a value that is in the local stack it is autometically going to promote the variable in the shared memory on the compiler which is also called
heap memory
NB. this is helpful when the function is very big/long , to know the return type we have to scroll down at the end of the function , by using named return we can avoid that
NB. this pattern is very common in go this left justifies our code as much as possible as we dont have to write the arternative code isdise else block
NB.if we want to read outer scope stuff we have to pass that as argument / parameter or it might cause error in async code
NB. as they are types they can be stored in variable
NB. method reciver is what makes a function method in go , what this does is gives function a context were to execute , so we can do
g.greet()
methods are functions with syntactic suger that provides a contet the function should execute
getName
uses a copy ofman
, butsetName
uses a reference to man which is more efficient
if we return pointer from a set method we can make a builder
" the way interfaces are implemented in GO makes it so scaleable compared to java and other languages "
agenda
inside structs we define data but inside interfaces we describe behaviours (method defination)
in got we do no explicitly implement interface we do it implicitly
console writer hear can be replaced with any kind of struct that has method writer what is polymorphis behaviour
so what we can do is for a concreate type we can create an interface
if we have a single method interface we name the interface like method name + er
write+ er = writer
structs are the most common way to implement interfaces , but we dont have to use structs we can use any type
ex we dont have controll over int type as it is a primitive type we have controll over types that we define
if we comment out wc.Close()
we would get output
converting writer closer to buffer writercloser but notice we are using pointer
to stop this panic hear we can
// TODO this section needs more work
NB. nice thing about empty interface are everthing can be cast into an object that has no method written to it even primitivs
This is a very important note when working with interfac if any of the methods require a pointer or implementing own reciver we are going to have to implement that interface with a pointer if not through if all the methods require value type then we can go ahed and use value types but we could aslo use a pointer
implementing an interfce with value
implementing with pointer
when we are implementing an interface with value type all of the methods need to have value recivers (methods that implement the interface) if we implement with pointers we just need the methods regardless of the the recivers
so the method set for a value type is all the method with value recivers but method set for a pointer type is all of the methods with value recivers as well as pointer recivers (only for interfaces )
when we define types and we assign methods to them each one of those type has what is called a method set
now when we are working with methods directly the method set is all of the methods regardless of the recivers associated with that type
But with interfaces things work differently when we implement interface with concrete value the method set of the value , when we are taking in the context of interface is any method that has a value as a reciver and the method set if a pointer is the sum of all of the value reciver methods and all of the pointer reciver methods
Encouraged and supported by the go community and good to apply if our application its practical
use many , small interfaces , the samller the interface the useful and powerful they can be (applicable for any language)
if we dont need to xport and interface athen we wont (export concrete video ref (5.25.00)
design functions and methods to recive interace whenever possible
Agenda
ex how to create goroutine ?
go sayHello()
spins off a green thread and run the sayhello in the green thread .
the sayHello is in another go routine and our application exits as soon as the main function is done
most of the programming languages (PL) use os threads what it means they have an individual call stack handed to that thread these tend to be very very large talking 1mb of RAM quite bit of time for app to set up creation and distruction of thread is very expensive
GO follows a different model which is similar to Erlang
language which is green thread which creates an abstruction of a thread which we call go routine . GO scheduler maps these go routines on to the os thread and schedular will take then with cpu thread that available and assign every go routine certain amount of time on these threads
Go routines are very cheap to create and destroy so a go application can have many go routines at once
ex
this is bad practice but just for example
ex (clouser)
go has understanding of clouser
as we see using clouser like this can have unexpected results so we can write is like
ex (work application without sleep function)
mutex is used to lock resources
ex
its a very unique feature and makes go standout among other
most PL were design with a single porcessing were in mind when concurrency and perellelsim came in mind . when concurrency and perellelism came they were bolted on the side and had special packages when go was designed concurrency and parallelsim were considered
channels can help pass data between go routines in a way which is safe and prevents race condition and memory sharing problem
Agenda
ex
ex( async senders and recivers )
if the member of senders and recivers do not natch it is going to cause deadlock (PANIC)
only one message at the buffer at once to do otherwise we need buffered channels
ex( bideirectional routines )
ex( directional channel )
recive data from one side and send from another
Notice we are passing bidirectional channel and aorking with a single directional channel . hear the go routine understands the needs and does the casting itself so this is a kind of polymorphic behaviour
ex ( buffer channel)
Output
fatal error all goroutines are asleep - deadlock !
as the channels are asymetric sending by 2 and reciving from 1 at a time (Buffer can solve the problem)
adding buffer to a channel
this channel has a internal data store which can store 50 integers
buffer are also neededwhen the senders or recivers need a littel time to process and dont want to block the other side
when we are closing the channel we have to remember that we cant send any more data one the channel is closed . so we could defer a funcion to close the channel as if we always keep it open we might have memory leak
NB. cant send data in a closed channel and we cant also detect if a channel is closed from sending routine
to know from reciving routine
ex( logger implementation with channel)
but the logger needs to shutdown
now after the main function is done out logger function wripped down forcefully
to do it more greacefully we could do
one , with difer
two , with select statement , zero memory allocation is required in this process
now to singal done channel form the main
golang package for json in encoding/json
for encoding json.Marshal
for decoding json.Unmarshal
date type
GO | JSON |
---|---|
bool | boolean |
float64 | Numbers |
string | string |
nil | null |
array | array |
map/struct | Object |
ex
ex