Introduction

  1. An open source Programming language created at Google.
    1. Created as an internal programming language for Google infrastructure.
  2. Go is simple, minimal and progmatic
    1. Emphasis on solving practical aspect.
  3. Modern General purpose language
    1. Go is widely used for building backend systems
    2. Build System based applications as well as Infrastructue Tools like docker,Kubernetes,Terraform.
    3. Build for large scale backend and distributed systems
    4. Rust can be used for Systems level applications but it is complex but performs slightly better than Go.
  4. Statically typed language with high productivity.
    1. We specifically provide the data type.
    2. Easy to debug
  5. Compiles to Native machine code
    1. It complies quickly as compared to Other languages.
    2. Java compiles to intermediate byte code.
    3. We don’t need to package compiler separately.
  6. Garbage collected language
    1. Garbage collection is done automatically, which cannot be controlled manually.
  7. Inbuilt concurrency
    1. Can Leverage Multiple CPU cores
    2. Run autonomous jobs Independent of each other
  8. First appeared in Go 2009
  9. Gopher is the mascot of Go
  10. Go 1.0 was Released in March 2012
  11. Current version is 1.26
  12. Set up the development environment
    1. Download and, install Go: https://go.dev
    2. Create a GOPATH envirnoment variable
      1. 'export GOPATH=$HOME/go' >> ~/.bashrc
    3. Set the GOMODCACHE environment variable (Eg: export GOMODCACHE=$HOME/go/pkg).
      1. The directory where third-party libraries will be dowloaded
      2. export GOMODCACHE=$GOPATH/pkg
      3. The default location of the module cache is $GoPath/pkg/mod. To use a different location, set, the GOMODCACHE environment variable.
      4. The module cache Is the directory Where the Go command stores Downloaded module files. The module cache Is distinct from the build cache Which contains compiled packages and other build artifacts.
    4. Setup following environment variables
      1. GOMODCACHE=$GOPATH/pkg

      2. GOBIN=$GOPATH/bin

    5. Set the GOBIN environment variable - The directory where go commands will place binaries (executables)
      1. export GOBIN=$GOPATH/bin

      2. go install - Installs executables into GOBIN directory
    6. Add GOBIN to system path
      1. echo 'export PATH=$PATH:$GOBIN' >> ~/.bashrc
    7. Install GIT: https://git-scm.com
    8. Install an IDE, VS Code: https://code.visualstudio.com or use GoLand(https://www.jetbrains.com/go/)
      1. GOLand is a dedicated ID
    9. Check Installation with following commands
      1. go env GOMODCACHE
      2. go env GOBIN
      3. go env
      4. go version
  13. Starting up project
    1. create a root directory for your project
    2. Use command go mod init "{module_name}" to create a go.mod file
      1. This is a dependency management file
      2. This includes any third party libraries which we intend to use in our project.
      3. It is a mandatory file even if we don't use any dependencies.
      4.  Use command go mod init "{module_name}" to create  file
  14. In Linux Go Installation path is
    1. /usr/lib/golang
  15. Go has an opensource eco system.
    1. No License required for any libraries.
  16. Disadvantages
    1. It is not a very much feature rich programming language.
    2. C an C++ can perform bertter than go under certain conditions but Go performs better than Java and C#.
  17. In Go, we give two kinds of package names, either main or any other name.
    1. Main means It compiles to executables.
    2. Any name, other than main Then it is a library.
  18. Add import block and add libraries
    1. Standard libraries which are installed with Go.
    2. Third-party libraries Which are imported from vendors.
    3. Import defines the import block to import libraries
  19. Main is the entry point to executable programs
  20. Library packages Do not include main
  21. Go build command compiles all the “.go” source files from the directory and put the resulting binary into the same directory.
  22. To change the name of executable Use -o command 
    1. Go build -o “{Executable – name}”
  23. To create another Operating System specific build file use GOOS=Windows GOARCH=amd64 go build.
  24. Multiple main functions are not allowed.
    1. There should be only one entry point
  25. The executables created from Go do not need to install Go in another environment to run. These already contain some essential Go environment aspects.
  26. Go executables are very lightweight
    1. Very low and lightweight operating systems(Linux distribution) Have been created with Go. These require very less memory.
  27. Go install creates a build And install executables In GOBIN location.
  28. Go run Is used to run a Go file during development phase. It does not create a build file.
    1. We should always specify a file name with Go run command.
    2. It create an executable at temporary location.
    3. We can specify multiple files in Go run command.
  29. We can pass multiple files to run command.
  30. Add GoBin To system path So that executables can be run From any location.
  31. Go fmt formats code To resolve formatting issues during copy and paste.
  32. Go clean cleans/deletes the executables From current directory.
  33. Declaring variables in Go
    1. Var {var_name} string
    2. Local variables have a local scope that is scope is limited to function block only.
    3. Package levels variable have scope within the package.
      1. Package is a directory Where we organise source files.
    4. The keyword var Is used to declare variables
    5. Inside the functions, short assignment operator (:=) Can be used to declare and initialise variables without using var and datatype.
    6. Short assignment operator (:=) Can’t be used for declaring package level variables.
    7. The keyword const is used to declare constant variables.
    8. Go doesn’t provide enum So we have to use some constant mechanism to build enumerate.
    9. Short assignment operator is only needed at the time of declaration. When we reassign value to Variable Defined by short assignments, operator, we should not use the same.
  34. Loops
    1. There is no do while, while loops only for loop is there.
    2. An empty for loop Is an infinite loop.
    3. We can use for loop with only one statement as condition.
    4. We can exit from loop using break, We can skip in a loop using continue.
    5. In switch case Break is not mandatory in each case expression.
    6. There is a Range loop Specifically to iterate over Collection.
    7. There is break And continue via which we can control loops.
  35. We use func keyword to write Functions.
    1. Go functions can return multiple values.
    2. An empty interface in arguments supports any data type.
  36. There is No void keyword
    1. No datatype Needs to be mentioned for void return.
  37. We specify The data types in parenthesis when a function returns multiple values.
  38. We must maintain order while returning values.
  39. For a single data type parenthesis is not required.
  40. Functions can have Variadic parameter by using (“…”) syntax.
    1. Variadic parameter Is used to pass Variadic Number of values.
    2. The last parameter in Go can be a variadic parameter.
    3. We cannot have multiple variadic parameter.
    4. Variadic parameters are data type specific.
    5. In Variadic parameter We can pass many number of parameters.
    6. Variadic parameters are indexed from 0 to n number of values.
    7. For range loop is used to iterate over a variadic parameter.
    8. We can also pass a collection in place of Variadic variable.
    9. It is used when values are optional.
    10. If we pass nothing in a Variadic Number nothing is sent.
  41. Go support anonymous functions.
  42. In Go There is no try catch mechanism. It has a built in data type called as error. This is used to handle errors.
  43. Most functions Latest returned value is an error value. The caller function checks If the error value is NULL or not To check successful execution.
  44. If we do not want to return a value in a case, we can return “-“ underscore. An underscore Is a blank identifier In Go.
    1. This means in place of second identifier We are ignoring the values.
    2. Blank identifiers (“-“) Are ignored by the compiler and compiler shows No error on them.
  45. There are no warnings in Go. There are only compiler error.
  46. Array, Slice and map are also called as composite types.
  47. Slice is a dynamic array in go.
    1. The difference between variadic parameter And dynamic array Is for dynamic array We should always pass a value.
    2. In a Variadic parameter We can also pass a zero number of values Which we can’t do in a dynamic array.
  48. Functional Go
    1. Functions are values in Go
    2. They can be assigned to a variable
    3. Such an assignment is called as function value.
    4. A closure is a function value that references variables form outside the body.
    5. The function may access and assigned to the reference variables, in this sense, the function is “bound” To the variables.
    6. The logic in a Closure function Is given by Caller function.
    7. Functional programming is based on immutable data structures. No mutable data, no state(or implicit state).
    8. Functions are first class citizen in the go programming language.
    9. Go functions are like values
    10. Go supports higher order functions.
      1. Takes one or more function as parameter’s.
      2. Functions can return functions
    11. Go supports closure a function value that references Variables declared outside its body.
    12. Go is not a functional programming language, but can Leverage its capability.
    13. We can also pass functions as parameters.
  49. Every go source file must start with a package main.
  50. When we are using multiple source files dependent on each other we must specify all of them in a go run command or use "go run ." to run all files.
  51. Go provides three types of data structures to work with collection
    1. Arrays all fixed length collection
      1. Array is a value type data structure.
      2. We can use any type of the type in array. That is it can be user defined, primitive or collection type.
      3. All values in an array are initialised to default values.
      4. Array is fixed length data structure which is its limitation.
    2. Slices a dynamically sized collection
      1. Slice is a dynamic array built on top of normal array.
      2. Slice is a three field data structure
        1. Has a pointer that points to an underlying array
        2. Length specifies the length of an underlying array.
        3. Capacity specifies the capacity of the array.
      3. Slices can be enlarged at any time using built-in function append().
      4. A built-in copy function can be used for creating bigger slices by copying contents from existing slice.
      5. Slice is completely a go specific Data structure not found in other programming languages.
      6. Capacity is an optional property of slice which specifies pre allocated memory block.
      7. Pointer points to an array.
      8. Length is the length of underlying array.
      9. Whenever performance is critical. We use the capacity parameter here allocation becomes quick.
      10. By default, both length and capacity will become same while initialising.
      11. In slice we may not give length while declaration.
      12. A nil slice is a slice which has been declared but not yet initialised.
        1. Capacity is not mandatory while declining/initialising slice.
      13. Slice can be initialised either by using make function or by using literal expression.
        1. We can also specify index-based values while initialising a slice.
      14. We can also pass a variadic parameter in append.
      15. We can also pass another slice in the append method.
      16. Slice represents a sliced part of data where inner bound starts with one.
      17. We can remove the inner and outer bound to get entire data from a slice for example copy_slice=slice[:]
    1. Maps is a collection of key/value pairs.
      1. Go provides a built in map type that implement a hash table.
      2. Map is a collection of Key/value pair, which is an unordered collection.
      3. The built in delete function removes An entry from the map for the given key.
      4. Map provides a faster data revival for a Given key.
      5. To iterate over the contents of a map Use the for range keyword.
      6. A hash table is an unordered collection of key value pairs.
      7. Every element/Memory block is uniquely identified by the key and the memory blocks Which are not in any order.
        1. In array And slice There is an order of memory blocks.
      8. Keys work like indexes
      9. Reading is very fast by specifying unique key We can retrieve The value element in very faster manner.
      10. Map is An unordered collection.
      11. A nil map Is a map which is declared, but not initialised.
      12. All the reference types must be initialised 
        1. Channel can only be initialised using make.
      13. We can only insert data after initialising Our data structures.
      14. For range iterator is used to iterate over a map.
      15. We must provide data structure of both keys and values.
      16. To retrieve Data from map, we can use one variable or 2 variable option.
        1. With one Variable option, if keys exist The corresponding value will be retrieved. otherwise, default value will be received. There is no way to know if the value exist or not.
          1. lan:=langs[“EL”]
        2. With two variable option, which is a better Approach in first variable, we will get the value if the value exist or not. The second variable is a Boolean expression If key exist Boolean value is true else false value.
          1. lan,ok := langs[“EL”]
      17. For Insert and update We use same mechanism. If we overwrite a key That is Reassign value to a key It will be An update expression.
      18. To check existence of a key retrieve it using 2 variable And check Boolean value.
      19. While retrieving values They may not be An order in their, retrieval As it is an is unordered.
      20. Keys are always unique in a map
    2. Channel is another built data structure which is reference type.
    3. Struct(interface) is a user defined datatype which can be a value or a reference.
  52. Slice map and channel or a part of concurrency programming.
  53. Slice and map are reference types, which must be initialised either by using built-in, make function or literal expression.
  54. Slice,map and channel can be initialised using make function. We can initialise Slice and map using literals.
  55. In Go, there is a function called as init()
    1. init is executed automatically before Main()
    2. It is used to initialise package level variables.
  56. In Go, we have literal expression that is using curly brackets {} we can initialise a value.
    1. When we do with array we call it a array literal.
      1. We can specify/initialise values at specific index with array literal.
    2. When we do with Slice we call it a slice literal.
    3. When we do with a Map we call it a map literal.
    4. We use literal assignments with short assignment operator.
    5. We initialise all the values in a single expression.
    6. We can also use a 3 dot("...") operator to specify length of a value. In this case, we do not need to specify numeric length specifically. It automatically takes based on number of elements.
  57. Go provides very limited number of built in functions.
  58. Default value of a string datatype is empty string.
  59. We can use normal for loop to iterate over get data structures but better is to use for range expression.
    1. We can use for range to iterate over only keys, only values or both key and values.
    2. When using for range for only values we must use a blank identifier for keys.
    3. For range can be used to iterate over array, slice, map, channel, variadic parameter.
  60. Any unused variable is considered as a compiler error in go.
  61. We must use a blank identifier in this case for example, while defining keys and values while iterating a list and only using values.
  62. The built in append function check for available capacity. If it is less than required it dynamically. allocates them.
    1. Available capacity is also referred to as pre allocated memory.
  63. To write multi line expressions in Go, use a “,”
  64. Defer keyword
    1. The keyword defer is used to schedule a function call to be executed right after a function returns.
    2. Defer keyword is used to defer/schedule a function call to the moment the srrounding function returns.
    3. Defer is used to write cleanup code for example closing connections etc.
    4. Defer function executes in a bottom up manner that is the function deffered last will execute first.
    5. Defer executes in all situations even after runtime exception/panic etc.
    6. All Defer statements are executed in bottom up manner.
    7. We can have an inline defer function
    8. Defer functions are executed in last in first out manner.
    9. https://github.com/gauravmatta/golang/tree/main/basics/defer
  65. Panic Function
    1. The built in panic function is used to stop the execution that will provide a panic situation.
    2. Panic function is used to throw exception and sop execution.
    3. When we run our program any unhandeled exception will trigger the panic function.
    4. The panic function stops the execution.
    5. We check for error and then send the error in panic function.
    6. Any type can be passed to a panic function.
    7. Panic is used for throwing run type exception like File Not Found,Configuration Errors,Database Connections,Errors during bootstrapping etc.
    8. Panic is not a good situation to have.
    9. Panic is raised in scenarios where continuing execution further does not means any sense and needs to be stopped.
    10. Use of Panic is optional.
    11. Defer statements are executed in bottom up order before panic stops the execution.
    12. Panic propogates to the caller and after that program stops execution.
    13. https://github.com/gauravmatta/golang/tree/main/basics/panic
  66. Recover Function
    1. The built in recover function is called within a deffered function to regain control over a panicking function.
    2. Recover is used to regain control over panic situation in defer functions.
    3. The defer statements include a recover function.
    4. Recover function returns a value provided by panic function.
      1. We can operate on value and regain control.
    5. In Recover also all the defer functions are executed.
    6. After recover the execution resumes from the caller function after the called function statement.
    7. Recover is mostly used in HTTP Requests on REST API systems.
    8. Recovery mechanism is mostly for Runtime Exception.
    9. Recover is used to prevent system crashes in particular situation so that other operations are not impacted.
    10. In HTTP request each request is processed by a different handler so one bad request should not crash the entire system.
    11. The runtime exception does not propogate to entire server and server will not crash.
    12. In every request api service we use a panic recovery.
    13. Panic recovery is only for run time, exception And not for all panic conditions.
    14. https://github.com/gauravmatta/golang/tree/main/basics/recover
  67. Error Handling
    1. Error Handling Is used to manage exceptions.
    2. Go doesn’t have a try Catch mechanism So it cannot throw errors to parent/caller functions.
    3. Go takes errors As values just like functions.
    4. Go provides a builtin data type called as error.
      1. In case of error We create a variable Of type error And returned from function.
    5. There is a standard library of errors in go.
    6. This provides essential parameters to create error data type variable.
    7. The library helps us to create different type of error objects.
    8. Generally go functions, return error as The last value as they return Multiple data types.
      1. Generally, the last return value is the error value sent.
      2. This convention is followed by the most Go developer Community.
      3. If there is no error We return a nil value for error.
      4. All other values are specified before the error value.
    9. The errors library Provides a function called as New.
      1. When we pass string in the function It returns a data type of type error Which we can return from our functions
      2. It is better to create a package level variable for error values If we have multiple error values.
    10. We can also customise errors using errorf function in fmt library To send a custom error Message which has a %w verb Which stands for wrap and error With some context specific information. This helps us to wrap information With error.
    11. We can check a condition on type of error Using “Is” Function in errors library.
    12. We can unwrap the error Using unwrap Method in error library. This only works with wrapped error using errorf.
      1. If the error Has not been wrapped the error returns nil value.
  68. We may need to write much boiler plate code in Go.
  69. Architecture of Go
  70. Packages
    1. Go programmes are organised into directories is called as packages.
    2. Go provides two kinds of packages
      1. Package main for which the resulting binary will be an executable, a shared library package to be used for other packages.
    3. Package main should have an entry point main function
    4. Packages are identified using their case for access.
      1. Package identifier starting with upper case letter will be exported to all other packages.
      2. Package identifers starting with lower case, letter will not be exported to other packages, but it will be available across the same package.
    5. To modularise and organise our code, we need libraries.
    6. Library packages, are reusable
    7. We should not put entire code in package main.
    8. Go uses naming conventions for public/Private accessibility identification
    9. Packages can have init function, which can be used for writing initialising logic at package level. This will be involved before invoking main function.
    10. The keyword import is used to import packages into Go source files.
    11. Packages can be imported by providing an alias name.
    12. Packages can be imported by providing _(underscore) as an alias name, which is used for importing a package just for invoking init functions
    13. Third-party packages are installed using Go get command.
    14. The Go module introduced in Go 1.11 as an experimental feature, has become an official solution for dependency management since Go 1.16.
    15. Init function is used in both main package as well as library packages.
    16. All the init functions are executed when other libraries are called in a package.
      1. The order of init is not a matter of concern. It execute in order libraries are imported.
    17. The import block can be used for importing Standard library package and third-party library package.
    18. A library package is an independent unit, and it should not depend on other library packages.
    19. We can import a package with An alias name.
    20. Main packages compile into an executable.
    21. Most of the code is in library packages. Only few code is in main.
    22. If we want 2 executables We will create two main packages.
    23. Package. Main only contains code to start the application. Main is basically an entry point With Some supportive code.
    24. In a real world system, we have lot of packages.
    25. When we write a library package, we give a package name, other than main.
      1. We should use lowercase letters
      2. _ Are not allowed
      3. - Can be used in some cases.
      4. Names should be short.
      5. Plurals Should not be used.
    26. The Go.mod file contains all the entries of third-party libraries.
      1. These are automatically added once we add/use third-party libraries in our project.
    27. Our Library Structure depends on our directory structure.
      1. Generally Package name is same as directory name Of the file. Technically, we can have a different name. There is no problem in that.
    28. All files in package, access package level variables.
    29. Function names starting with Capital letters are accessible in the files that include that package.
    30. We should create a separate directory in package for main.
    31. While importing packages, we first import the standard library package, then we import the third-party libraries, then we import custom libraries. Between all these, there must be Given a line break.
      1. Basically, we import library in three sets.
    32. Module name in Go.mod file is our root name
      1. we import libraries using {go mod}/Path to package of file.
    33. We create different libraries for different business domains.
      1. Separate library for database persistence.
      2. Separate library for business logic.
    34. These packages are called from another packages.
    35. When we import our library package, optionally, we can have an alias name.
      1. Alias Purpose is to give shorter name for reference.
      2. Alias name Is written before the package.
    36. We may in some cases have different package name, then directory name. The same should be used while importing package.
    37. If we have provided alias, we should use it for reference. We cannot use the original name.
    38. In order to use third-party library, we need to download or install using “go get package name”
    39. Once we install a third-party library, its supporting libraries are also installed And added to go.mod.
    40. To use it in our code, we import the same.
    41. go.mod Is basically a dependency management solution’s for third-party libraries.
    42. We can search for libraries on pkg.go.dev.
    43. We have standard library package, SQL, which supports multiple databases.
    44. A method/variable with same name cannot be repeated across multiple source files in a package.
    45. Go.mod file is a part of Go module.
    46. Go module is a dependency management, solution, for third-party libraries.
  71. User defined type
    1. Go type system provides two user define type types
      1. Struct
        1. It is used for creating concrete user defined types.
        2. A struct Is a collection of named Fields.
        3. Behaviour can be added to a Struct Type by specifying receivers.
        4. There are two types of method, receiver, value receiver, and pointer receiver.
        5. Methods receiver are not special, they are just functions.
        6. Pointer receiver can be used for two scenarios
          1. Mutates the state of types.
          2. Type that need more memory.
        7. We can have a struct Without properties, this is called as An empty structure.
        8. Struct Tags
          1. Struct Tag is used to create a metadata For each attribute to be used for some other package.
          2. Struct Tag, lets you provide some meta data to be used for other packages, mostly for encoding packages.
          3. REST API Communicates using json format or xml format.
            1. Now a days All people use json format.
          4. If we provide tagging information while defining struct Tag that information is used for encoding packages.
            1. So we can provide information like json names To be used for an Attribute during json encoding.
            2. We use packages like encoding/json and encoding/xml to define tagging information
          5. Struct Is mostly used for encoding packages.
          6. Jason must follow industry standards from http://jsonapi.org
            1. Example all keys should be lowercase.
          7. All the attributes of struct Must start from a capital letter to make them public and usable across Packages
            1. tagging is used to bridge this name casing gap Between struct and json standards.
            2. We can add attributes like omit empty To remove a value from json if empty.
      2. Interface
        1. It is used for specifying Contracts.
        2. Interfaces, are behaviour contracts To concrete types, which that you define behaviour for your objects.
        3. Interfaces are implicitly satisfied
        4. In Go, explicit declaration of interface implementation is not required. We just need to implement the methods defined in the interface into our struct type To implement an interface type.
        5. In object oriented programming, a protocol or interface is a common means for unrelated objects to communicate with each other.
        6. Interface provide hidden implementation.
        7. The bigger, the interface, the weaker, the abstraction
    2. Go has no classes.
    3. Methods can be added to any type.
    4. Go has no inheritance.
    5. Type stand alone by themselves, they just are and have no hierarchy.
    6. Go type system provides type embedding, which allows us to embedded struct types Into other struts To create bigger types using composition.
    7. Be conservative in what you send, be liberal in what you accept from others.
    8. A structure is a lightweight class. A struct has a state Defined by its properties or fields.
    9. A struct has operations Which define its behaviour and are declared as methods.
    10. Struct datatype Isolate between property and behaviour.
    11. Property and behaviour are defined in different bodies or files.
    12. We define structs Only by using properties, methods are added later.
    13. In Go struct Instances can be either value type of reference type.
    14. Value type struct Use memory of the stack frame.
      1. Once the function is completed, all memory is automatically removed.
    15. In reference type, we have to manually write code for memory allocation and deallocation Of memory, Post usage.
    16. With inheritance, we have Type hierarchy, in a long chain Of multilevel inheritance. As the chain expands, this can become complex, so Go does not support inheritance.
      1. Go recommend composition over inharitance.
      2. Composition is implemented using type embedding
    17. We cannot convert between types in go.
    18. There is no hierarchy/relationship between types in go.
    19. We can only embed types in Go.
    20. Type assertion is not possible in Go.
    21. We can have any number of embedded types.
    22. In the same file, we can have more than one structs Which may be embedded or not in each other.
    23. We can mutate struct Properties using functions.
    24. When we create a struct Receiver by value, each time we mutate A copy is created and mutated.
    25. Value receiver always creates a Value/copy and modify the same.
    26. Whenever we want to mutate We must create a pointer receiver.
  72. Reference type of struct.
    1. reference type are created by Garbage collector, and not stored in stack frame.
    2. Reference types are destroyed by garbage collector, and not removed from stack frame.
    3. Reference types are stored in heap memory.
    4. In a reference, type copy is not created.
    5. When ever we use a pointer in Go, we make it as a reference type.
    6. Reference, types are managed by Garbage collector.
    7. A copy is not created for mutation of reference types.
    8. Whenever we want to mutate, a property Then that method must be decorated with a pointer receiver.
    9. Go compiler has an escape analysis process, which can make decisions based on type of receiver that is pointer or value to be sent in a function.
      1. We should Try to use reference types with pointer receivers.
    10. Types that need more memory should also be represented with reference types for efficiency and better performance.
    11. Creation of reference type is not cost efficient So they should not be used everywhere.
      1. We need to allocate/deallocate resources Also, after use using garbage collector.
    12. We can also create reference types using new built in function without initialising.
    13. The value returned is reference to New zero value of that type.
    14. The “new” built-in function allocates memory. The first argument is a type, not a value, and the value returned is a pointer to a newly allocated zero value of that type.
      1. P1 := new(Person)
  73. There are four types of literals in go
    1. Array Literal
    2. Slice Literal
    3. Map Literal
    4. Struct Literal
  74. Struct Is used for concrete user defined type, whereas interface is used for abstract type.
  75. In Go type stand alone by themselves, they have no type hierarchy
  76. Interfaces
    1. Interfaces are behaviour contracts
    2. Interface types Provide contracts To concrete types , Which let’s you define Behaviour for your objects.
    3. Interfaces are implicitly satisfied.
    4. In Go, explicit declaration of interface implementation is not required. We just need to implement the methods defined in the interface into our struct Type to implement an interface type.
    5. In object oriented programming, a protocol or interface is a common means for unrelated objects To communicate with each other.
    6. For loose coupling between types, we should use interfaces or contracts.
      1. This is based on Liskov substitution principal that is designed by contract.
      2. A base class reference must be able to use reference to all derived classes Without knowing them.
    7. Interface is a contract which has to be fulfilled by its implementation.
    8. There is no implementation in interface.
    9. In Go interfaces are implemented implicitly that is do not need to specify its implementation syntax. We just need to implement methods and interface is implemented automatically.
      1. Interfaces, implicitly, satisfied
    10. Interface provides hidden implementation.
    11. The bigger, the interface, the weaker is the abstraction.
    12. Be conservative in what you send and be in what you accept from others.
    13. Any struct Implementing interface must provide a concrete implementation Of its methods.
    14. We can switch between types of an interface wherever it is used.
    15. We should always write loosely coupled code via interface.
      1. A loosely coupled code Looks clean and is easily testable and maintainable
    16. interface{}(Empty interface) Says nothing. 
    17. The keyword any is an alias to an interface.
      1. Any refers to An empty interface.It does not have any behaviour contract.
      2. fmt.println has a variadic any as a parameter Which lets It print anything.
      3. Reflection package which helps us to know the type of a variable also accepts NMT interface.
    18. All values(Numeric, String, array, Slice, map) are an implementation of Empty interface.
    19. In new versions of Go, we see any keyword.
    20. struct{}(Empty struct) Is a struct Type that has no fields.
      1. empty struct Does not take any value for allocation.
      2. Empty struct Is used in scenarios when we want to use an empty variable.
    21. Empty struct Occupies zero bytes of storage.
    22. Interface helps us to define code for single responsibilities.
      1. Every struct That implement the interface is designed for a single responsibility.
    23. Interface are open for extension, but close for modification as per open/close principal.
    24. The client should not be forced to depend upon interface methods that they do not use. This is stated in interface segregation, principal.
    25. Interface should depend and communicate on through abstraction.
    26. Interfaces should be implemented as per solid principles.
    27. interface makes it easy To manage our persistent code.
    28. It helps to provide mock implementation and write unit test cases of our code easily.
    29. Concrete implementation Is not easy to manage.
    30. Using interface, we will be using the high-level abstract level code. Thus implementation is hidden from us.
  77. The imports organised with standard libraries, First then a line break, Then third-party libraries , a line break And then our own libraries.
  78. Accept interfaces And return struts.
  79. Explicit dependencies: Methods and classes should explicitly require(Typically, through method, parameters or constructor’s parameters) Any collaborating objects, they need in order to function Correctly.
  80. Declarative composition: Remove the dependent logic from the composition process.
  81. Go doesn’t support any constructor mechanism.
  82. Nil can only be used with pointer, error, slice, map, channel.
  83. Concurrency
    1. By leveraging concurrency, we can write high-performance software Systems.
    2. Go is widely used for large scale distributed systems Where the concurrency capability give lot of advantage.
    3. In concurrency Programming, we can execute independent functions, concurrently Independently of each other, that is at same time. 
    4. We execute Millions of tasks at the same time using concurrency.
    5. Concurrency in Go is managed by a lightweight garbage collector and a concurrent environment/Concurrency runtime.
    6. Green threads are threads That are scheduled by a runtime library or virtual machine(VM) Instead of natively by the underlying operating system.
    7. In Go runtime There is a scheduler, which is responsible for creating and managing Go on time.
    8. The scheduler software Is based on an algorithm called as m:n Scheduler algorithm
      1. It is a Multiplexing algorithm
      2. M stands for Number of Go routines.
      3. N stands for Number of operating system threads.
      4. As compared to Go routines The number of operating system threads will be very limited.
        1. The number of operating system threads depends On the number of CPU cores.
        2. A single OS thread can be used for executing many Go routines.
        3. Go routine is a lightweight thread.
        4. In earlier version of a Go, A single Go routine Could be of size 4KB, now they have reduced it to 2KB.
    9. Go scheduler is a m:n Scheduler Which multiplexes(or schedules) m go routines On n OS threads.
      1. Scheduler is responsible to schedule the Go routines On limited, number of OS threads.
    10. In every Go programme at least one Go routine is there.
      1. Main function is the actual Go routine.
    11. In Go concurrency model, there are two primitives
      1. Go routines
        1. Go routine is a function that is running, concurrently.
        2. Go routine can be launched by placing the Go Keyword before a function.
        3. These are managed and created by Go runtime.
        4. These are executed based on a technique called as m:n Scheduler
          1. Maps m go routines to n OS threads.
        5. Go routines are kind of green threads. Also known as co routines.
        6. Go routine is a function running concurrently, independent of each other.
        7. The concurrency executables Contain a garbage collector and a concurrency runtime.
          1. Go runtime create a Go routine And assign against an operating system, thread that is bound to a CPU core.
          2. The management is done by concurrency runtime.
      1. Channels
        1. Channel provide a simple mechanism for Go routine to communicate, and a powerful construct to build sophisticated concurrency patterns.
        2. Channels provide a communication mechanism for Go routines to communicate with each other.
          1. Go routines Share data with each other.
    12. It follows a fork join model Once main is started As Go routine and then from it, child, Go routine, are created. Once work is done, it joins to main Go routine.
    13. To start something as a Go routine, just add Go keyword before it.
    14. We can write concurrent systems Without channels.
    15. Non-concurrency programs Lead to blocking code.
      1. These are also called as sequential programmes.
    16. Sync package provides a WaitGroup Counting semaphore Which is typically used to wait for a group of semaphores or task to finish.
      1. Weight group is mostly used in concurrency programming model.
      2. Sync package provides synchronisation mechanism.
      3. WaitGroup Add method, add the number of times, our semaphore can be used.
        1. Each time we call it, it increment value to the wait-group counter.
      4. WaitGroup Should either be a pointer or a package level variable. It should not be a copy.
      5. WaitGroup Done method decrements, the counter by one.
      6. WaitGroup wait method waits until The counter goes zero before proceeding with execution.
        1. It acts as a blocker.
      7. Wait Group Is used to synchronise the concurrently executing activity.
      8. A wait group Is a counting semaphore Typically used to wait for a group of go routines or tasks To finish.
      9. Wait method Blocks Until the wait group task counter, is zero.
      10. Done function decrements , the weight group Task counter by one. It is equivalent to add -1.
      11. Wait Group add method adds a numeric value To the wait group counter.
      12. Wait group Must be passed as a reference because it acts as a semaphore or it should be a Package level variable.
      13. When we write a Go function inside another Go function/inner function, we should define a separate wait group Mechanism for it.
      14. New method creates a pointer. If we don’t use New while initialising each time a wait group variable, whenever the variable is passed. A copy is created.
        1. Whenever we need to create reference use New.
      15. A wait group must Not be copied after first use.
      16. In programming, we use two kinds of memories
        1. Stack frame
          1. When we execute a function of stack frame is created.
          2. Whenever we create a local variable of value type in that function, it is pushed into stack frame.
          3. Once the function completes, the entire stack frame is removed automatically.
        2. Heap memory
          1. In a function, if we use a pointer or a reference type, it is stored in a heap memory.
          2. In heap memory Manual allocation and deallocation is needed.
          3. In reference type, there is no use of a copy.
      17. Inner function Can use the same wait group variable without pointer. Only when function is outside, it should be passed as a pointer.
      18. Wait, group done function should generally be a defer function
        1. It should logically beon the top
      19. In reference type, same memory is shared across the function.
        1. Heap type Uses dedicated heap memory.
  84. Channel is a data type used in concurrency programming
    1. It can be created using any data type.
    2. It is used to share data between autonomous tasks.
    3. We may create a channel of empty struct Which may not be used to send data.
    4. Empty struct Is mostly used in concurrency programming.
    5. Channels provide a simple mechanism for  go routines to communicate, and are a powerful construct to build sophisticated concurrency patterns.
    6. Go routine is a concurrently executing function.
      1. It is called by Go keyword followed by function name.
      2. It is executed as an autonomous task that is a concurrently executing activity, independent of each other.
      3. We need to take care of synchronisation of Go using wait group Mechanism.
      4. Wait group is not a part of concurrency It is just a mechanism to control a Go routine function.
    7. Most of the time concurrency is a composition of autonomous tasks.
    8. We break a big task into small tasks and we execute them concurrently for achieving a common goal.
    9. These tasks may need to share data between themselves.
    10. Channel is a communication mechanism in go concurrency programming model.
    11. Communication mechanism between go routines.
    12. Channel is a conduit/pipe For communication between two Go routines.
    13. Channel has two principal operations
      1. Send
      2. Receive
    14. Send let us send data to channel data structure.
    15. Receive helps us to receive a data sent on a channel.
    16. There are two types of channel
      1. Un buffered channel
        1. No storage mechanism in the channel.
        2. Also known For synchronous communication.
        3. Blocks sending Go routine or receiving Go routine Until corresponding, send or receive happens on the same channel.
        4. Blocks a send an operation Until a corresponding receive operation can be executed from different, Go routine.
        5. If receiving operation is executed, First, it will block receiving Go routine Until sending go routine Can execute a send operation Since the un buffered channel Cannot hold any data.
        6. Both send and receive will be executed at the same time And data will be received synchronously.
        7. If receive operation execute First, it will be blocked as data is not available in the channel.
        8. Un buffered channel blocks are sending Go routine or Receiving Go routine Until a corresponding send or receive is happening on same channel.
          1. Such, a channel is also called as synchronous channel and communication is called as synchronous communication.
      2. Buffered channel
        1. Has a buffering capability that is temporarily storing the data.
        2. There is a buffing capability whenever we have a send operation It is not blocked.
        3. Data goes to temporary storage mechanism so that whenever a receive operation executes On same channel that data can be received without any blocking behaviour.
        4. Stores Up to the capacity elements and provides FIFO Semantics.
        5. A synchronous communication happens.
        6. A buffer channel can be initialised using a capacity
          1. If capacity is hundred we can make hundred send operations without any receive operation.
          2. Send operation can be made without any blocking behaviour.
        7. Hundred memory blocks are available Because we initialised as hundred capacity.
        8. When we make a receive operation A memory is released because once data is consumed that memory block is freed.
        9. It is a temporary storage mechanism until a receive operation is performed on the channel.
        10. Once all blocks are full, and we try to make another send operation Then it works exactly like a un buffer channel that is it blocks the operation.
        11. The 101. Send operation Without any corresponding, will get blocked until any receive operation can execute from a different routine.
        12. Once a receive happens One memory block will be freed So that 101 send operation Can get a memory block In the buffered channel.
        13. With un buffered channel Send First will be blocked until a corresponding receive operation could execute from the same channel and different go routine.
        14. In buffered Channel with specific capacity, a send operation is executed Without any blocking operation as data is stored in a buffer.
        15. Buffer channel is called as asynchronous, channel and communication is known as a synchronous communication.
        16. It stores up to its capacity and provides First in First out semantic whenever we make a receive operation.
        17. The first insertion/send operation will be the first receive operation That is based on First in First out semantic.
        18. The message is sent through asynchronous medium.
        19. Buffered acts like a message queue.
    17. In concurrency Go routine We cannot predict the order sometimes send operation is executed first, sometimes they receive operation is executed first.
    18. Slice, map, and channel or by default reference types, which should be initialised via literals{} or make.
      1. Channel can only be initialised by make().
      2. In order to create our own reference type, we can create a pointer or use a new built in function.
        1. new(sync.WaitGroup)
        2. &sync.aitGroup
    19. We use chan and datatype to declare a channel
      1. var ch chan string
      2. We need datatype because channel is used to send and receive data.
      3. Data type can be primitive,collection or user defined.
      4. Once defined Send and Recieve will happen with that particular datatype
    20. A channel declared but not initialized is called as an nil channel.
    21. We initialize a channel using make(chan string))
    22. If we initialize a channel with a second parameter of numeric value we specify it's capacity.
      1. make(chan string,3)
    23. This creates a buffered channel with capacity greater than zero.
    24. Buffered channel is initialized with a predefined memory block.
    25. We use a channel operator (<-) To perform Send /receive Operation on a channel.
      1. v:=<-channel Is used to receive value from a channel thus performing receive operation.
      2. Channel<-5 Is used to perform, send operation thus sending value to a channel.
      3. When we make a send operation, the channel operator is on the right side.
      4. When we make a receive operation Channel operator is on the left side.
    26. When we make a send operation on unbuffered channel With No receiver, it block the executing Go routine.
    27. Close function is used to close a channel from sending operation. But we can execute receive on the closed of channel.
      1. If we try to make send operation on close channel We will get a runtime exception or a panic scenario.
    28. We must close a channel once all sending is completed.
    29. V:=<-channel Is used to receive data. If data is not available, we will get a default. Value of variable. It will also be a Blocking code.
    30. V,exist : <-channel Is used to get data from Channel. 
      1. Exist checks for data on channel.
      2. V Will get default value in case of no data.
      3. exist==true
        1. Data received from channel.
      4. exist==false
        1. Channel was closed, no more data left in the channel
        2. Receive default value
      5. Blocking code because send has not happened, No data available in the channel. Waiting for send operation.
    31. Len function Can be used to find length of data in a buffered channel
      1. Len Function Cannot be used on non-buffer channel.
    32. Whenever we make a send operation on a async channel, the executing go routine Block till the time receive operation is performed on a channel.
    33. Go channel mechanism doesn’t provide a broadcasting operation that is a value cannot be shared by many Go routines Only one Go routine Can receive the data.
    34. Data is shared in a first in First out manner, the go routine Which executes receive First gets the data.
    35. Multiple go routines Can Simultaneously recieve, the different data from the buffered.
    36. Job can be distributed as more than one go routines can recieve data in sequence.
    37. Closing of channel is not mandatory, but we should close it in real world to avoid Concurrency issues related to messages being Send when not required.
      1. This is a risk in distributed environment.
    38. For range Expression is used to continuously execute receive operation channel is closed.
      1. It may receive irregular values.
    39. When the send is stopped it is better to close the channel.
    40. If send and receive, Happening continuously That is Background worker is sending messages continuously. In such rare scenarios, we may not Close channel.
  85. Go routine Is An independent unit of work.
  86. These, independent Units of work communicate through a channel.
  87. If we Receive before Send, it will create a panic situation that is a runtime exception.
  88. Channel acts as Signalling Mechanism Which signals for data Received from a go routine.
  89. Pipeline concurrency pattern is used in concurrency where a big task is divided into small task. Output of one Go routine will be the input of second go routine , Output of second Go routine will be input of third Go routine and so on. This goes on till the number of sub Tasks/go routine We have are executed in order.
    1. It works like a pipeline
    2. For example, first Go routine finds 10 random numbers Then the second Go routine, find the Fibonacci values For the each value sent by First Go routine And then this fibonacci Is Printed using a third Go Routine.
  90. A channel has basically three operations Send, receive, and close using these, we can achieve many technical solutions.
    1. Channel is a reference type so when we pass it into a function, it will not be a value, but A reference That is will refer to same object.
    2. After completing the Send operation We close the channel.
    3. For range can be used to loop through the channel buffer to receive Values continuously.
      1. We can also use for loop, but better is to use for range
    4. The for range loop Will only exit when we close a channel else, it will wait for getting the data, and it will get a blocking behaviour. Eventually, we will get a deadlock and a runtime panic.
    5. Receive operation can have three different behaviours
      1. receive data from channel
      2. Channel is closed, no more values we receive a default value
      3. Channel will get blocked that is code will get blocked, data is not available and is waiting for getting a send operation.
    6. Channel mechanism helps in orderly execution of Go routines, which by default, independent and concurrent in nature.
      1. It helps us to control go routines
    7. Generally The go routine which does not depend on receiving data from any channel is the one which Initialise execution.
    8. If we put channel operator on the right side of the “chan” keyword It is a Send operation. When we give channel operator on the left side of the “chan” keyword It is a receive operation.
      1. We call it channel direction
    9. If we define this direction as a parameter in Go routine Then, in the routine, we are bound to that operation within the channel.
      1. If we pass “in <- chan int” Then, in the Go routine, we can only receive integer from above channel.
      2. If we pass “out chan <- int” Then in the Go Routine, we can only send Integer from the channel Specified
      3. This makes code more readable and predictable.
  91. Slice, map and channel will always be reference in Go, so when we pass as an argument We may not Make it as a pointer.
  92. In Programming concurrency Is the composition of independently executing processes, While Parallelism is the Simultaneous execution of computations, which may be or may not be related to each other.
    1. Concurrency is about dealing with lots of things once. Parallelism is about Doing lots of things at once.
  93. There is no one to one mapping between a Go Routine and an operating system thread.
    1. Single thread Can be used for executing several thousands of Go routine.
    2. Go routine is not a thread But a single lightweight, thread.
  94. We can limit our threads Using runtime library package. We can limit CPU cores etc
  95. By default, a channel behaviour is by directional, unless until we specify directional operator.
  96. Select case is a switch case like syntax in Go, but for channel operation.
    1. If we are receiving data from two channels in a routine Then there is a dependency.Data received from channel 2 Maybe blocked till the time Data is not available in channel 1.
    2. We can switch between channels based on data availability in channels
    3. Select case evaluate the expression to receive data if data is available in a particular channel, it statements are executed.
    4. Helps to eliminate Unnecessary blocking behaviour in case of multiple channels.
    5. We can also perform a time out wait Using time, library after function
      1. time.After(3* time.Second)
    6. If More than one Case match, Go will randomly select A case And execute the Expressions.
    7. If we have data for any channel, then that data should be received immediately and processed if Go routine is free.
    8. A Variable Declared in case expression can be declared again in next case expression.
    9. Case works for both Send and receive operations Of channels.
  97. HTTP programming
    1. Go is widely used for writing backend services, basically for HTTP and GRPC.
    2. HTTP programming is a request response, programming model.
    3. HTTP Client sends a request to the server.
    4. Server serves the request And sends back a Response back to the HTTP client.
    5. In Go, standard library package net/HTTP, provides the essential functionalities for writing HTTP applications.
      1. Net/Http package provides A Foundational layer. It provides essentials for HTTP programming.
      2. Major components of net/HTTP
        1. ServeMux(struct): HTTP request Multiplexer(router)
          1. ServeMux Is used to match the URL pattern and execute corresponding method/implementation.
          2. ServeMux Is also called as HTTP request router.
          3. ServeMux is used to configure all the URI Patterns. If there is a match in incoming URI And configured URI pattern, then Some implementation is executed.
          4. We can create an instance of ServeMux And call its Methods to perform operations.
        2. Handler(Interface): Serve the HTTP request. Writes, headers And bodies into HTTP response.
          1. The implementation that ServeMux serves is called as A handler, which is an interface.
          2. Using handler, we send back the response back to the client.
          3. Handle interface has a method ServeHttp(ResponseWriter, *Request)
          4. Both ResponseWriter and request come from Same HTTP Library.
          5. Response writer is an interface type. Its implementation is already provided by HTTP library when we start this server. We just have to work with it. We do not need to provide its implementation.
          6. Request is used to extract information from a HTTP client request. All the request parameters, all the request body, the form values we can extract from the HTTP request object.
          7. Request is a struct type.
          8. By using response, writer and request object, we can serve any request.
          9. We should provide a concrete implementation of the handler interface.
        3. HandlerFunc component.
          1. HandlerFunc Component Is An adapter to allow the use of ordinary functions as HTTP handlers.
          2. HandlerFunc is an implementation of handler interface.
            1. type HandlerFunc func(ResponseWriter,*Request)
            2. func (h HandlerFunc) ServeHTTP(w ResponseWriter,r* Request)
          3. We do not need to provide a separate implementation for each URI If we use a HandlerFunc
          4. The signature of HTTPFunc is same as  ServeHTTP function.
          5. HandlerFunc is a function type, We should pass a function type in it as a parameter.
          6. http.NewServeMux Returns a pointer/reference to serve Mux type.
            1. ServeMux is our RequestRouter
            2. Lot of methods are there in ServeMux to configure our URI pattern.
    6. Handler is an interface To serve our HTTP request. We create a type of HandlerFunc Which is an implementation of handler.
    7. Once we configure all the methods and URI patterns using handler method of NewServeMux. We start our server.
    8. ServeMux Handles function is used to configure URL and methods. It has two parameters URL and handle function which can be created through HandlerFunc.
    9. Server is started using ListenAndServe Function of HTTP library, which takes ServeMux As parameter and address.
      1. ServeMux Is also An implementation of handler interface.
    10. We specify A verb before URL to specify Type of API example “POST /register”.
      1. By default, request is GET.
    11. For other features, we use a third-party library like to enhance HTTP router, et cetera.
    12. There are also web application framework available to develop applications in Go.
    13. It is not practical to create handler implementation For each of our handlers, so we use HandlerFunc.
    14. By using ServeMux We can configure the URI pattern and a built in handler Implementation.
      1. We use HandlerFunc for handler implementation.
    15. ServeMux HandlerFunc function
      1. Instead of using handle method Of ServeMux We can also use HandleFunc Which is also an implementation of Handle.
      2. It takes two parameters
        1. Pattern string
        2. HandlerFunc(ResponseWriter,*Request)
          1. Second parameter is a function and not An interface.
      3. It allows us to directly plug-in a handler to a URI pattern.
      4. So we need not provide a concrete implementation of handle interface.
      5. Handle Func of ServeMux Internally calls the handle method.
      6. The code is much simpler than handler Call.
      7. Internally all code is dependent on handler interface.
      8. Internally implementation of handler interface is called.
      9. Also for ListenAndServe We create A server object, where we pass port and handler.
      10. We use this server object to Call ListenAndServe.
      11. ListenAndServe in HTTP only initialises two properties The port and router.
      12. To Customise Our server, further, we directly create server object where we can customise more properties like error log, write time etc.
      13. Using the server object we Call ListenAndServe.
    16. In modern web applications, server is An REST api or GRPC API.
      1. Client is a browser that is a Java script application that calls API.
    17. Conventional web apps had server, which used to provide the server side code And UI code for web interface.
      1. We had cookies to save session state.
    18. By default, web application are stateless and not statefull
      1. we can make them state full using DB persistence(key,value),cache, Cookies, et cetera, or any storage mechanism.
      2. Session on stateless uses cookies to maintain data
      3. We can use context object in the HTTP request object to store data.
    19. Gin is the Most popular web application framework in Go.
    20. Echo is another Web application framework in Go
    21. Best is not to use any framework
    22. In REST API We use a unique URI Along with a verb. Based on URI And verb, identify a resource Which will be provided from the server.
      1. Verb can be GET,POST,PUT,DELETE
    23. To develop a web Application in Go, we can Follow following Sequence
      1. Start with the model and define the Constant and interfaces.
      2. Add Memory  store implementation.
      3. Add a handler implementation And inject memory into that.
      4. Create a server, Create a memory Instance, create handler instance And inject the Handler Instance, Create a ServeMux instance and integrate.
    24. ServeMux is also an implementation of a handler interface.
    25. When we work on HTTP Application
      1. We use net/http + third party libraries
        1. We use third party to extend some functionality for example replacing ServeMux with another router etc.
        2. chi is a very popular router implementation library which is very feature rich.
          1. It is compatible to go standard library package.
      2. Another approcah is to use web framework
        1. Gin is a very famous web framework
        2. Second popular framework is echo
          1. In echo there is a global error handelling mechanism that sends an error in http format back to client.
          2. We can return error directly from hander in Echo framework
        3. Frameworks provides helper methods example to decode an encode etc.
        4. We can add additional properties to handler function in a framework using a middleware.
          1. Example we have a panic recovery middleware,Logger middleware or Authorization Middleware.
    26. Middlewares are automatically attached to a handler function.
      1. Http middlewares are plugable functionality that can be decorated to all the handler functions.
      2. Middleware functionality is executed with each route this can be either before or after.
      3. Middlewares are Pluggable and self-contained piece of code that wraps web application handlers.
      4. These are Components that work as another layer in the request handling cycle, which can execute some logic before or after executing your HTTP application handlers.
      5. Great for implementing cross-cutting concerns: Authentication,authorization, caching, logging,panic recovery etc.
      6. Web Application Frameworks provide lot of middlewares.
      7. In Java filters and interceptors are used to implement middleware.
      8. Cross cutting concerns are not part of a core application Logic, but are used across application.
        1. Example authentication, authorisation, panic recovery Et cetera are called as cross Cutting concerns
      9. A Middleware Accept an implementation of handler interface And returns an implementation of Router interface.
        1. Since it returns, handler interface Value, we can use it for registering a route.
      10. We can apply middleware to individual route specific level or we can apply to entire router instance.
      11. If we are using framework, we need not write middleware's The framework itself Provides many necessary middleware.
    27. mux was a very popular router library before servemux. 
    28. Gin and Echo framework provide a wrapper context over seperately handelling ResponseWriter and Request in Handler Functions.
      1. The context contains Request and Response objects and also provides helpers for encoding Json and Decoding Json etc. 
    29. In Gin we pass context as a pointer where as in Echo we don't pass it as a pointer but as a value.
    30. In Gin library if we create a router using Default() method then it automatically attaches Logger and Recovery middleware to each of the handlers by default.
  98. Go Modules
    1. There are a few challenges with package dependencies 
      1. Dependency management of third-party packages
      2. Go get Always takes Latest version of packages.
    2. Modules are how Go manages dependencies.
    3. A single module is a collection of related Go packages that are version together as a single unit.
    4. A module is defined by a tree of Go source files With a Go.MOD file in the tree’s root directory.
    5. Modules record, precise dependency requirements and create reproducible builds.
    6. Modules must be semantically Version in the form, V(major).(minor).(path) such as v0.1.0,v1.2.3 or v3.0.1(checkout http://semver.org)
    7. Uses minimum version selection algorithm.
    8. Go modules manage third-party dependences.
    9. Workflow with Go modules
      1. go mod init Will Automatically initialise a module with file go.mod.
      2. Go get will, automatically Update the go.mod file.
      3. Go get, will allow version selection to be overridden by adding an @version Suffix or “module query” To the package argument.
        1. go get github.com/gorrila/mux@v1.6.2
        2. go get github.com/gorilla/mux@‘<v1.6.2’
      4. The environment variable configured using “go mod cache” Is the Path, where these third-party libraries are cloned once referred by Go get command.
      5. By default, it takes the latest version.
      6. In go.mod File, it makes an entry.
        1. If the entry is followed by a comment, indirect, then it means that even though we have installed, we have not reference the library in our code.
      7. Go mod Tidy Will synchronise the source code entry with the entry in Go mod File.
        1. We should run this command before Committing code in version control and before compiling.
        2. Go mod tidy ensures That the go.mod File matches the source code in the module. It adds any missing module requirements necessary to build the current module packages and dependencies, and it removes requirements on modules that don’t provide any relevant packages. It also adds any missing entries to go.sum And remove unnecessary entries.
        3. If the library is not being used/referenced Go mod tidy Will remove it from go.sum file.
      8. go mod edit - Provides a command-line interface for editing and formatting go.mod files, for use primarily by tools and scripts. (Eg: go mod edit -replace mycopmany.io/greetings=../greetings)
      9. go mod download - Downloads the named modules into the module cache (GOMODCACHE)
      10. go list -m - Print path of main module
      11. go list -m -f={{.Dir}} - Print root directory of main module
      12. go list -m all - View final versions that will be used in a build for all direct and indirect dependencies
      13. go get -u ./... or go get -u=patch ./... (from module root directory) - Update all direct and indirect dependencies to latest minor or patch upgrades
        1. Running Go get command with “-u” Flag update the version.
        2. -u means Update to latest version.
        3. This flag is mostly not used once we have included library in our code
      14. go build ./... or go test ./... (from module root directory) - Build or test all packages in the module.
      15. go.sum file is created to uniquely identify each library.
      16. For every library, a hash is created in this file.
      17. go.sum File is a part of go.mod File
        1. This file should be committed along with source file And go.mod file.
      18. If we don’t want to use a library Reference in our file, we can reference using “_” To avoid compiler error.
        1. “_” Is called as blank identifier.
      19. In order to work with databases, we use a standard library package called as “database/sql”.
      20. For each library, we have two entries in the go.sum file.
  99. Web framework in Go should be used in rare cases.
  100. In Go function can be treated as a value, so we can directly pass a function in functions like HandlerFunc.
  101. If we need to use error values Across the project, then we should create a package level error values.
    1. If we need to create domainlevel error values We can put in same file as entities.
  102. We should create a repository type For handling CRUD operations.
    1. We can provide persistence for this interface, then in our DB memory store.
  103. If we write a function name, it will not be invoked But if we write a function name with brackets “()” It will invoke the function.
    1. In the later case It will pass function as a value That is when we write only function name.
  104. Unit Testing
    1. test driven development
      1. Write unit test before writing production code.
      2. Test driven development is also called as Red-Green-Refractor.
      3. First, we define the test, and then we define its implementation until the test passes. This stage is called as green.
      4. Code should be highly testable And clean
      5. Once the test is green That is it passes we refactor the code.
    2. Define behaviour before writing code
      1. example user should be able to create customer
      2. Customer ID should be unique.
    3. Testing in Go
      1. “testing” Is the foundation library for unit testing.
      2. “net/http/httptest” Helps in writing test for HTTP application.
        1. ResponseWrite and Server object.
    4. Naming convention for writing unit test
      1. Test Suit file: Go source file In which you write unit tests Where the name should end with _test.go
      2. Test function func TestXYZ(t *testing T)
    5. “Go build” and “Go install” exclude all files whose name end with _test.go
    6. “Go test” compiles The entire Package source and runs unit test cases from the test, suit file.
    7. We write test suit file In the same Package Directory, where we write project code.
      1. We can have a different Directory though in some cases/ Specific scenario, but preferred approach is same package Directory.
    8. Test function name should start with a “Test” Followed by alphanumeric name.
      1. The function should accept a parameter(t *testing T)
    9. Testing library doesn’t provide an assertion mechanism. So we assert using a third-party library.
      1. github.com/stretchr/testify/assert
    10. To execute test, we use “go test -v”
      1. -v stands For verbose Which shows details
      2. To get test coverage use “- cover”.
    11. Unit testing can be at functional level or user story level.
    12. Table testing
      1. Run uni tests using “go test ./…”
      2. We write test cases for a bunch of behavioural aspects and not a single behaviour.
      3. We Create a table(Collection) Of test cases or user stories.
      4. We create a slice of a struct Which has following properties
        1. Name of test case
        2. Entity for which test case is defined
        3. Expected value of error/response
    13. Go provides a mechanism for sublevel testing, where we can Iterate through the above, slice and test
      1. To run the sublevel test, we use function t.run(name,test function())
      2. In the test function, we use the Expected value.
    14. We should always try to segregate different concern in different modules. For example, HTTP controller should not handle persistence. It should be handled by separate services.
      1. we achieve this by injecting Repository in a controller.
      2. When we define code based on their behaviour/concern in separate module injected in each other, each module can be mocked Need basis. This makes code more testable.
      3. For example, during testing repository can be mocked When injected into the controller So, actual data is not impacted.
      4. In unit test, we look for individual components, isolated from dependencies
        1. For handler, we should only focus on request and response, isolated from dependencies Such as repository or service.
    15. net/http/httptest
      1. ResponseRecorder
        1. ResponseRecorder Is an implementation of http.ResponseWriter Interface that records its mutations for later inspection in tests.
      2. Server : Test http server For use in end to endHTTP Test.
      3. When we call handler function, we need request and response object.
      4. To test handler, we use response recorder from above library
      5. ResponseRecorder is an implementation of response writer interface.
      6. For all handler Where will pass ResponseWriter We pass ResponseRecorder.
      7. ResponseRecorder Can be created Using httptest.NewRecorder().
      8. To mock objects, we use gomock library
        1. gomock library is maintained by uber.
        2. Mocking services in controller
    16. BDD with ginkgo
      1. create one suit for a single package and one for multiple spec file.
        1. Bootstrapping is a suit : ginkgo bootstrap
      2. Adding specs to a suit
        1. Adding specs to a suit : ginkgo generate
  105. Nil can only be used for Reference types like map, channel, error, slice
    1. Nil is used as a pointer
  106. Generics
    1. Generics are a way of writing code that is independent of the specific types being used.
    2. With generic, you can declare and use functions or types that are written to work with any of a set of types Provided by calling code.
    3. Functions and types are now permitted to have type parameters. A type parameter list looks like an ordinary Parameter list, except that it uses Square Brackets instead of parenthesis.
    4. func SumNumbers[K comparable, V number](m map[K]V) V{ }
    5. Generics were Recently added to Go.
    6. For example, if we want to use same logic on the floating type and integer type Array/collection We can write a common generic type.
      1. If we do not have generic types, we will have to write separate functions.
    7. We use “ Comparable” Type to Support all types in Go.
      1. This is helpful in Maps “key” values.
    8. We can also create an interface to support selective types
      1. This is called as a constraint contract.
    9. We define generics In square brackets after function name
      1. We can provide selected type for a generic Parameter or use a comparable
    10. We can also use alias types In generics.
    11. We can add user defined types as well.
    12. We can also create a struct with generic.
    13. Keyword “any” Is represented as an Empty interface, which means any value can be passed.
      1. Generics are basically Used for collection data structures.
  107. Comparable vs any
    1. Both are predeclared constraints used with generics, but they serve different purposes.
    2. Any
      1. Alias for interface{} — accepts every type
      2. Use when you just need to hold or pass a value of unknown type
      3. You cannot use == or != on values constrained by any
    3. Comparable
      1. Accepts types that support == and != operators
      2. Includes: int, float64, string, bool, pointer, struct (with comparable fields), array, channel
      3. Excludes: slice, map, func (these can’t be compared with ==)
      4. Comparable is an interface that is implemented by all comparable types.
  108. Slices and maps are utility libraries That provide operations on slice and map, respectively.
  109. Logging/Log
    1. Package “log/slog”
    2. Package slog Provides “ Structured logging” In which log records include a Message, a severity level, and various other attributes expressed as key value pairs.
    3. It defines a Type,Logger, Which provides several methods such as (loggerInfo and loggerError) for reporting events of interest
    4. Each logger Is associated with a handler. A logger output method creates a record from the method arguments and passes it to the handler, which decides how to handle it. There is a default logger accessible through top level functions(Such as Info and Error) That Call the corresponding Logger methods.
    5. A Log record Consist of a time, a level, a message and a set of key value pairs where keys are string and values may be of any type.
    6. Example slog.info(“hello”,”count”)
    7. Log level
      1. Type level Int
      2. A level is the importance or severity Of a log event. The higher the level, the more important or severe the event.
        1. Const(LevelDebug Level=4,LevelInfo Level=0,LevelWarn Level=4,LevelError Level =8)
    8. Initially, logging was done through third-party libraries.
    9. In Recent lator versions Go has included a library called as “log/slog” Which can be used for enterprise applications.
    10. Third-party libraries may have a lot of internal third-party dependencies with other third-party libraries. So they may create Dependency Compatibility issues.
    11. Structured, logging records, logs, tracing and implementation
      1. We achieve Observability pattern using this.
    12. Structured logging includes a lot of information in key value pairs.
      1. This information is then used by log analysis tools like Kibana
    13. slog was Included in Golang version 1.22.
    14. Slog functions provide First parameter as message, which is a string, and then variadic parameters Of key value pairs.
    15. We should often use The function LogAttrs of slog library.
      1. LogAttrs Has following parameters.
        1. Context, which can be empty or Nil value
          1. Context is mostly passed as Nil using context.Background().
        2. Level, we provide as information level/log level
        3. Log message as string
        4. Variadic parameters of Struct “Attr” type(accepts key value Pair)
          1. example slog.String(“created by”,user)
          2. Slog.Int(“orderId”,O.id)
      2. For production systems, we should use slog.LogAttrs() method.
    16. We can use New() Function of slog To add our writer implementation to logger.
      1. slog.New(slog.NewTextHandler())
      2. slog.New(slog.NewJsonHandler())
        1. With Jason handler, data is captured in Jason format.
    17. Logging is treated as a high-level module Thus, we should inject it as a Dependency like persistence in module.
  110. Package Context
    1. Package context defines the Context type, which carries deadlines, cancelation signals, and other request-scoped values across API boundaries and between processes.
    2. Context type Is used to create a context object.
    3. Context value is created by using context package methods
    4. Context.context can also be used to hold key value pairs of data.
    5. Contact is heavily used in concurrency programming.
    6. While creating context with any function, we Add a Parent context. Initially, the parent context is null So we pass context.Background.
    7. Context created using:
      1. WithCancel
        1. We have to manually Call the cancel function.
        2. WithCancel Returns a context And a cancel function. The cancel function is used to send a cancellation signal wherever We pass this context.
      2. WithCancelClause
        1. we can pass error value Else same as with cancel.
      3. WithDeadline
        1. Is called internally by With time out.
        2. We have to define the deadline/time
        3. Automatically calls the cancel()
        4. It starts the timer after the first time cancel method is called
        5. Cancel is Generally used with defer function
      4. WithDeadlineClause
        1. We can pass error value else As same as With deadline.
      5. WithTimeout
        1. We Define a timeout, That time out Defines the deadline/time, thus Internally calling WithDeadLine.
        2. Use defer cancel() to evaluate function, which starts the timer.
      6. WithTimeoutClause
        1. we can pass error value else same as WithTimeout.
        2. (context,duration,error)
      7. WithValue
    8. Do not pass a nil Context, even if a function permits it. Pass context.TODO if you are unsure about which Context to use.
    9. Use context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions.
    10. The same Context may be passed to functions running in different goroutines; Contexts are safe for simultaneous use by multiple goroutines.
    11. func DoSomething(ctx context.Context, arg Arg) error {}
    12. We can check channels for signals from Go routine, and if work is done, we may need to stop go routine.
    13. A context can pass signals with following data.
      1. Cancellation
        1. We may need to send a cancel signal to a leaking Go routine/Unnecessarily running Go routine.
        2. Context.done() Method Returns an empty struct Once Context is cancelled.
          1. Empty struct Doesn’t take any memory and is used for signaling closure in concurrency programming.
          2. We can also send error Value with cancel, which is received in context.Err()
        3. If we use “with the cause” then cause() Method will Return a Non nil value.
        4. Cancellation signal is send in withCancel and withTimeout
          1. Withtimeout internally calls withdeadline.
          2. In withDeadline We need to provide exact date and time which is unrealistic in many cases, so basically we use withTimeout.
        5. Context.Done() should always be used with a select case.
      2. Key Value Pair of data
        1. Used Highly with GRPC API.
        2. We use WithValue function.
        3. In GRPC Programming Server Side Methods Have a Context And request object and it returns response object.
          1. Context object contains key value pairs like authorisation token, et cetera.
          2. This key value pair is defined With value.
        4. This value can be extracted From our server implementation.
    14. We can use these context in combination as well. We have to define a parent child relationship But in this case, we should create a parent child relationship in context.
    15. In withCancel, withDeadline, withTimeout We cannot create a key value pair.
    16. Context is used to share data between middleware And route specific handler functions.
      1. Middlewares are used for wrapping route specific handler function with the some extra pluggable information.
      2. Always middleware logic is executed first
  111. Working with SQL Databases
    1. For working with SQL databases, there is a unified approach, but for other noSQL Database, we should use a vendor specific package as there is no unified approach
    2. In Go standard library package, there is a package called as "database/sql" provides a generic interface for SQL (or SQL-like) databases.
    3. The database/SQL package needs some vendor specific implementation.
      1. In vendor specific package We have init function Which initialise’s SQL package.
      2. We can easily move from one database to another database by changing the implementation.
    4. The sql package must be used in conjunction with a database driver:
      1. https://go.dev/wiki/SQLDrivers
    5. We should never use API of vendor specific package. If we import vendors specific package along with database/sql package.
    6. Approaches
      1. Write SQL statements in Go code with database/sql package
      2. Use an ORM
        1. GORM: https://gorm.io/
          1. Go ORM Is a vert lightweight And most commonly used library.
        2. Ent: https://entgo.io/ (by Facebook Open Source)
          1. ENT is used next to Go ORM And is developed by Facebook. This project is currently maintained by Linux foundation.
          2. Instagram has also contributed to this project
          3. It has a very vast ecosystem.
          4. Once we use domain model of this ORM We can generate code for REST API , GRPC API.
          5. This ORM Is not light weight.
      3. Compile SQL to type-safe Go code(https://sqlc.dev)
        1. This approach is called as SQLC.
        2. This approach is now being used by other developer communities too.
        3. This approach was started by open source, Go community.
        4. In SQLC we create a configuration file, which has information regarding our database.
        5. We also provide SQL files for queries and schema.
        6. We use “sqlc generate” to generate code corresponding to schema file.
        7. Initially, SQLC was designed for python only, but due to its popularity, it’s expanding for other languages as well like Go.
    7. To perform a create operation, we use db.exec() Function.
      1. It returns a result and error
    8. Query Function returns, multiple rows
    9. QueryRow Returns a single row.
    10. DB also has an integration with context and using execContext(context,query) function We can pass context.
      1. Context should always be the first parameter when passed in any library.
    11. We should try to use context compatibility, API wherever possible.
  112. References
    1. https://go.dev/
    2. blog.golang.org/gopher
    3. https://github.com/shijuvar/gokit
    4. https://github.com/gauravmatta/golang
    5. https://pkg.go.dev/
    6. https://shijuvar.medium.com/
    7. https://martinfowler.com/articles/richardsonMaturityModel.html
    8. https://semver.org/
    9. https://jsonapi.org/
    10. https://docs.sqlc.dev/en/stable/overview/install.html

Comments