Documente Academic
Documente Profesional
Documente Cultură
Go Programming Language
The Go Programming Language, also commonly referred to as Golang, is a general-purpose
programming language, developed by a team at Google. The Go language was conceived in
September 2007 by Robert Griesemer, Rob Pike, and Ken Thompson at Google. Go first
appeared in November 2009, and the first version of the language was released in December
2012. The official web site of the Go project is http://golang.org/. Go has its own elegance and
programming idioms that make the language productive and fun to code. Go also provides a
comprehensive standard library. The standard library provides all the core packages
programmers need to build real-world, web and network-based programs. Go is a statically
typed, natively compiled, garbage-collected, concurrent programming language that belongs
primarily to the C family of languages in terms of basic syntax.
The Go Programming Language is an open source project that is distributed under a BSD-style
license to make programmers more productive. Go is expressive, concise, clean, and efficient
programming language. Go compiles quickly to machine code yet has the convenience of
garbage collection and the power of run-time reflection. It's a faster, statically typed, compiled
language that feels like a dynamically typed, interpreted language.
Go is a compiled language, and like many languages, it makes heavy use of the command line.
Go is both the name of the programming language and the name for the toolset used to build and
interact with Go programs.
Go is a statically typed programming language. What that means is the compiler always wants to
know what the type is for every value in the program. When the compiler knows the type
information ahead of time, it can help to make sure that the program is working with values in a
safe way. This helps to reduce potential memory corruption and bugs, and provides the compiler
the opportunity to produce more perform-ant code. Go struct lets you create your own types by
combining one or more types, including both built-in and user-defined types. Structs are the only
way to create concrete user-defined types in Go. When you create your own types using struct, it
is important to understand that Go does not provide support for inheritance in its type system, but
it favors composition of types that lets you create larger types by combining smaller types. The
design philosophy of Go is to create larger components by combining smaller and modular
components. If you are a pragmatic programmer, you will appreciate the design philosophy of
Go that favors composition over inheritance because of its practical benefits. The inheritance of
types sometimes introduces practical challenges with regard to maintainability.
In the last decade, computer hardware has evolved to having many CPU cores and more power.
Nowadays we heavily leverage cloud platforms for building and running applications where
servers on the cloud have more power. Although modern computers and virtual machine
instances on the cloud have more power and many CPU cores, we still can't leverage the power
of modern computers using most of the existing programming languages and tools. Concurrency
in Go is the ability for functions to run independent of each other. Its concurrency mechanisms
make it easy to write programs that get the most out of multi core and networked machines,
while its novel type system enables flexible and modular program construction. When a function
is created as a goroutine, it's treated as an independent unit of work that gets scheduled and then
executed on an available logical processor. Goroutines are created by calling the Go statement
followed by the function or method that you want to run as an autonomous activity. The Go run-
time scheduler is a sophisticated piece of software that manages all the goroutines that are
created and need processor time. The scheduler sits on top of the operating system, binding
operating system's threads to logical processors which, in turn, execute goroutines. The scheduler
controls everything related to which goroutines are running on which logical processors at any
given time.
Chapter 2: Variables
Golang Variables
A variable is a name that represents a data stored in the computer's memory. Here're some
important things to know about Golang variables:
Golang is statically typed language, which means that when variables are declared, they either
explicitly or implicitly assigned a type even before your program runs.
Golang requires that every variable you declare inside main() get used somewhere in your
program.
You can assign new values to existing variables, but they need to be values of the same type.
A variable declared within brace brackets {}, the opening curly brace { introduces a new scope
that ends with a closing brace }.
The keyword var is used for declaring variables followed by the desired name and the type of
value the variable will hold.
You can declare a variable without assigning the value, and assign the value later.
package main
import "fmt"
func main() {
var i int
var s string
i = 10
s = "Canada"
fmt.Println(i)
fmt.Println(s)
}
After the execution of the statements above, the variable i will hold the value 10 and the variable
s will hold the value Canada.
The assignment of a value occurred inline with the initialization of the variable. It is equally
valid to declare a variable and assign a value to it later.
package main
import "fmt"
func main() {
var i int = 10
var s string = "Canada"
fmt.Println(i)
fmt.Println(s)
}
The integer literal 10 is assigned to the variable i and the string literal Canada is assigned to the
variable s.
You can omit the variable type from the declaration, when you are assigning a value to a variable
at the time of declaration. The type of the value assigned to the variable will be used as the type
of that variable.
package main
import (
"fmt"
"reflect"
)
func main() {
var i = 10
var s = "Canada"
fmt.Println(reflect.TypeOf(i))
fmt.Println(reflect.TypeOf(s))
}
The := short variable assignment operator indicates that short variable declaration is being used.
There is no need to use the var keyword or declare the variable type.
package main
import (
"fmt"
"reflect"
)
func main() {
name := "John Doe"
fmt.Println(reflect.TypeOf(name))
}
package main
import (
"fmt"
)
func main() {
var fname, lname string = "John", "Doe"
m, n, o := 1, 2, 3
item, price := "Mobile", 2000
fmt.Println(fname + lname)
fmt.Println(m + n + o)
fmt.Println(item, "-", price)
}
Scope of Variables Defined by Brace Brackets
Golang uses lexical scoping based on code blocks to determine the scope of variables. Inner
block can access its outer block defined variables, but outer block cannot access inner block
defined variables.
package main
import (
"fmt"
)
var s = "Japan"
func main() {
fmt.Println(s)
x := true
if x {
y := 1
if x != false {
fmt.Println(s)
fmt.Println(x)
fmt.Println(y)
}
}
fmt.Println(x)
}
Note that short variable declaration is allowed only for declaring local variables, variables declared
within the function. When you declare variables outside the function, you must do so using the var
keyword.
A name must begin with a letter, and can have any number of additional letters and numbers.
A variable name cannot start with a number.
If the name of a variable begins with a lower-case letter, it can only be accessed within the
current package this is considered as unexported variables.
If the name of a variable begins with a capital letter, it can be accessed from packages outside
the current package one this is considered as exported variables.
If a name consists of multiple words, each word after the first should be capitalized like this:
empName, EmpAddress, etc.
Variable names are case-sensitive (car, Car and CAR are three different variables).
Zero Values
If you declare a variable without assigning it a value, Golang will automatically bind a default
value (or a zero-value) to the variable.
package main
import "fmt"
func main() {
var quantity float32
fmt.Println(quantity)
When the above code is compiled and executed, it produces the following result −
0
0
false
Variables declaration can be grouped together into blocks for greater readability and code quality.
package main
import "fmt"
var (
product = "Mobile"
quantity = 50
price = 50.50
inStock = true
)
func main() {
fmt.Println(quantity)
fmt.Println(price)
fmt.Println(product)
fmt.Println(inStock)
}
Chapter 3: constants
Golang Constants
A constant is a name or an identifier for a fixed value. The value of a variable can vary, but the
value of a constant must remain constant.
The keyword const is used for declaring constants followed by the desired name and the type of
value the constant will hold. You must assign a value at the time of the constant declaration, you
can't assign a value later as with variables.
package main
import "fmt"
func main() {
fmt.Println(PRODUCT)
fmt.Println(PRICE)
}
You can also omit the type at the time the constant is declared. The type of the value assigned to
the constant will be used as the type of that variable.
Constants declaration can to be grouped together into blocks for greater readability and code
quality.
package main
import "fmt"
const (
PRODUCT = "Mobile"
QUANTITY = 50
PRICE = 50.50
STOCK = true
)
func main() {
fmt.Println(QUANTITY)
fmt.Println(PRICE)
fmt.Println(PRODUCT)
fmt.Println(STOCK)
}
Name of constants must follow the same rules as variable names, which means a valid constant
name must starts with a letter or underscore, followed by any number of letters, numbers or
underscores.
By convention, constant names are usually written in uppercase letters. This is for their easy
identification and differentiation from variables in the source code.
You will learn more about Data Types, in our Golang Data Types tutorial.
Data Type
Go is a statically typed programming language. This means that variables always have a specific type and
that type cannot change. The keyword var is used for declaring variables of a particular data type. Here is
the syntax for declaring variables:
On the left we use the var keyword to declare a variable and then assign a value to it. We can declare
mutiple variables of the same type in a single statement as shown here:
Multiple variables of the same type can also be declared on a single line: var x, y int makes x and y both
int variables. You can also make use of parallel assignment: a, b := 20, 16 If you are using an initializer
expression for declaring variables, you can omit the type using short variable declaration as shown here:
We use the operator : = for declaring and initializing variables with short variable declaration. When you
declare variables with this method, you can't specify the type because the type is determined by the
initializer expression.
package main
import "fmt"
func main(){
var x int = 1 // Integer Data Type
var y int // Integer Data Type
fmt.Println(x)
fmt.Println(y)
package main
import "strconv"
func main() {
strVar := "100"
intVar, _ := strconv.Atoi(strVar)
strVar1 := "-52541"
intVar1, _ := strconv.ParseInt(strVar1, 10, 32)
strVar2 := "101010101010101010"
intVar2, _ := strconv.ParseInt(strVar2, 10, 64)
}
ParseFloat converts the string s to a floating-point number with the precision specified by
bitSize: 32 for float32, or 64 for float64. When bitSize=32, the result still has type float64, but it
will be convertible to float32 without changing its value.
package main
import (
"fmt"
"strconv"
)
func main() {
s := "3.1415926535"
f, _ := strconv.ParseFloat(s, 8)
fmt.Printf("%T, %v\n", f, f)
s1 := "-3.141"
f1, _ := strconv.ParseFloat(s1, 8)
fmt.Printf("%T, %v\n", f1, f1)
s2 := "-3.141"
f2, _ := strconv.ParseFloat(s2, 32)
fmt.Printf("%T, %v\n", f2, f2)
}
float64, 3.1415926535
float64, -3.141
float64, -3.1410000324249268
ParseBool returns the boolean value represented by the string. It accepts 1, t, T, TRUE, true,
True, 0, f, F, FALSE, false, False. Any other value returns an error.
package main
import (
"fmt"
"strconv"
)
func main() {
s1 := "true"
b1, _ := strconv.ParseBool(s1)
fmt.Printf("%T, %v\n", b1, b1)
s2 := "t"
b2, _ := strconv.ParseBool(s2)
fmt.Printf("%T, %v\n", b2, b2)
s3 := "0"
b3, _ := strconv.ParseBool(s3)
fmt.Printf("%T, %v\n", b3, b3)
s4 := "F"
b4, _ := strconv.ParseBool(s4)
fmt.Printf("%T, %v\n", b4, b4)
}
bool, true
bool, true
bool, false
bool, false
package main
import (
"fmt"
"reflect"
"strconv"
)
func main() {
var b bool = true
fmt.Println(reflect.TypeOf(b))
package main
import (
"fmt"
"reflect"
"strconv"
)
func main() {
var f float64 = 3.1415926535
fmt.Println(reflect.TypeOf(f))
fmt.Println(f)
package main
import (
"fmt"
"reflect"
"strconv"
)
func main() {
var i int64 = -654
fmt.Println(reflect.TypeOf(i))
fmt.Println(i)
import (
"fmt"
"reflect"
)
func main() {
var i int = 10
fmt.Println(reflect.TypeOf(i))
i16 := int16(i)
fmt.Println(reflect.TypeOf(i16))
i32 := int32(i)
fmt.Println(reflect.TypeOf(i32))
i64 := int64(i)
fmt.Println(reflect.TypeOf(i64))
}
int
int16
int32
int64
import (
"fmt"
"reflect"
)
func main() {
var f32 float32 = 10.6556
fmt.Println(reflect.TypeOf(f32))
f64 := float64(f32)
fmt.Println(reflect.TypeOf(f64))
f64 = 1097.655698798798
fmt.Println(f64)
f32 = float32(f64)
fmt.Println(f32)
}
float32
float64
1097.655698798798
1097.6556
import (
"fmt"
"reflect"
)
func main() {
var f32 float32 = 10.6556
fmt.Println(reflect.TypeOf(f32))
i32 := int32(f32)
fmt.Println(reflect.TypeOf(i32))
fmt.Println(i32)
f64 := float64(i32)
fmt.Println(reflect.TypeOf(f64))
}
float32
int32
10
float64
chapter 6: operators
Golang Operators
An operator is a symbol that tells the compiler to perform certain actions. The following lists
describe the different operators used in Golang.
Arithmetic Operators
Assignment Operators
Comparison Operators
Logical Operators
Bitwise Operators
Arithmetic Operators
The arithmetic operators are used to perform common arithmetical operations, such as addition,
subtraction, multiplication etc.
The following example will show you these arithmetic operators in action:
package main
import "fmt"
func main() {
var x, y = 35, 7
x++
fmt.Printf("x++ = %d\n", x)
y--
fmt.Printf("y-- = %d\n", y)
}
You should see the following output when you run the above program −
Assignment Operators
The following example will show you these assignment operators in action:
package main
import "fmt"
func main() {
var x, y = 15, 25
x = y
fmt.Println("= ", x)
x = 15
x += y
fmt.Println("+=", x)
x = 50
x -= y
fmt.Println("-=", x)
x = 2
x *= y
fmt.Println("*=", x)
x = 100
x /= y
fmt.Println("/=", x)
x = 40
x %= y
fmt.Println("%=", x)
}
You should see the following output when you run the above program −
The following example will show you these comparison operators in action:
package main
import "fmt"
func main() {
var x, y = 15, 25
fmt.Println(x == y)
fmt.Println(x != y)
fmt.Println(x < y)
fmt.Println(x <= y)
fmt.Println(x > y)
fmt.Println(x >= y)
}
You should see the following output when you run the above program −
Logical Operators
Logical operators are used to determine the logic between variables or values.
Operator Name Description Example
&& Logical And Returns true if both statements are true x < y && x > z
! Logical Not Reverse the result, returns false if the result is true !(x == y && x > z)
The following example will show you these logical operators in action:
package main
import "fmt"
func main() {
var x, y, z = 10, 20, 30
You should see the following output when you run the above program −
Bitwise Operators
Signed right Shift right by pushing copies of the leftmost bit in from the left, and let the
>>
shift rightmost bits fall off
The following example will show you these bitwise operators in action:
package main
import "fmt"
func main() {
var x uint = 9 //0000 1001
var y uint = 65 //0100 0001
var z uint
z = x & y
fmt.Println("x & y =", z)
z = x | y
fmt.Println("x | y =", z)
z = x ^ y
fmt.Println("x ^ y =", z)
z = x << 1
fmt.Println("x << 1 =", z)
z = x >> 1
fmt.Println("x >> 1 =", z)
}
You should see the following output when you run the above program −
chapter 7: if else
Like most programming languages, Golang borrows several of its control flow syntax from the
C-family of languages. In Golang we have the following conditional statements:
The if statement - executes some code if one condition is true
The if...else statement - executes some code if a condition is true and another code if that
condition is false
The if...else if....else statement - executes different codes for more than two conditions
Golang - if Statement
The if statement is used to execute a block of code only if the specified condition evaluates to
true.
Syntax
if condition {
// code to be executed if condition is true
}
package main
import (
"fmt"
)
func main() {
var s = "Japan"
x := true
if x {
fmt.Println(s)
}
}
The if....else statement allows you to execute one block of code if the specified condition is
evaluates to true and another block of code if it is evaluates to false.
Syntax
if condition {
// code to be executed if condition is true
} else {
// code to be executed if condition is false
}
package main
import (
"fmt"
)
func main() {
x := 100
if x == 100 {
fmt.Println("Japan")
} else {
fmt.Println("Canada")
}
}
Syntax
if condition-1 {
// code to be executed if condition-1 is true
} else if condition-2 {
// code to be executed if condition-2 is true
} else {
// code to be executed if both condition1 and condition2 are false
}
package main
import (
"fmt"
)
func main() {
x := 100
if x == 50 {
fmt.Println("Germany")
} else if x == 100 {
fmt.Println("Japan")
} else {
fmt.Println("Canada")
}
}
The if statement supports a composite syntax where the tested expression is preceded by an
initialization statement.
Syntax
package main
import (
"fmt"
)
func main() {
if x := 100; x == 100 {
fmt.Println("Germany")
}
}
You will learn about Golang switch-case statement in the next chapter.
Chapter 8: if else
Like most programming languages, Golang borrows several of its control flow syntax from the
C-family of languages. In Golang we have the following conditional statements:
The if...else if....else statement - executes different codes for more than two conditions
Golang - if Statement
The if statement is used to execute a block of code only if the specified condition evaluates to
true.
Syntax
if condition {
// code to be executed if condition is true
}
package main
import (
"fmt"
)
func main() {
var s = "Japan"
x := true
if x {
fmt.Println(s)
}
}
Golang - if...else Statement
The if....else statement allows you to execute one block of code if the specified condition is
evaluates to true and another block of code if it is evaluates to false.
Syntax
if condition {
// code to be executed if condition is true
} else {
// code to be executed if condition is false
}
package main
import (
"fmt"
)
func main() {
x := 100
if x == 100 {
fmt.Println("Japan")
} else {
fmt.Println("Canada")
}
}
Syntax
if condition-1 {
// code to be executed if condition-1 is true
} else if condition-2 {
// code to be executed if condition-2 is true
} else {
// code to be executed if both condition1 and condition2 are false
}
import (
"fmt"
)
func main() {
x := 100
if x == 50 {
fmt.Println("Germany")
} else if x == 100 {
fmt.Println("Japan")
} else {
fmt.Println("Canada")
}
}
The if statement supports a composite syntax where the tested expression is preceded by an
initialization statement.
Syntax
package main
import (
"fmt"
)
func main() {
if x := 100; x == 100 {
fmt.Println("Germany")
}
}
You will learn about Golang switch-case statement in the next chapter.
Golang also supports a switch statement similar to that found in other languages such as, Php or
Java. Switch statements are an alternative way to express lengthy if else comparisons into more
readable code based on the state of a variable.
The switch statement is used to select one of many blocks of code to be executed.
Consider the following example, which display a different message for particular day.
package main
import (
"fmt"
"time"
)
func main() {
today := time.Now()
switch today.Day() {
case 5:
fmt.Println("Today is 5th. Clean your house.")
case 10:
fmt.Println("Today is 10th. Buy some wine.")
case 15:
fmt.Println("Today is 15th. Visit a doctor.")
case 25:
fmt.Println("Today is 25th. Buy some food.")
case 31:
fmt.Println("Party tonight.")
default:
fmt.Println("No information available for that day.")
}
}
The switch with multiple case line statement is used to select common block of code for many
similar cases.
package main
import (
"fmt"
"time"
)
func main() {
today := time.Now()
var t int = today.Day()
switch t {
case 5, 10, 15:
fmt.Println("Clean your house.")
case 25, 26, 27:
fmt.Println("Buy some food.")
case 31:
fmt.Println("Party tonight.")
default:
fmt.Println("No information available for that day.")
}
}
The fallthrough keyword used to force the execution flow to fall through the successive case
block.
package main
import (
"fmt"
"time"
)
func main() {
today := time.Now()
switch today.Day() {
case 5:
fmt.Println("Clean your house.")
fallthrough
case 10:
fmt.Println("Buy some wine.")
fallthrough
case 15:
fmt.Println("Visit a doctor.")
fallthrough
case 25:
fmt.Println("Buy some food.")
fallthrough
case 31:
fmt.Println("Party tonight.")
default:
fmt.Println("No information available for that day.")
}
}
package main
import (
"fmt"
"time"
)
func main() {
today := time.Now()
switch {
case today.Day() < 5:
fmt.Println("Clean your house.")
case today.Day() <= 10:
fmt.Println("Buy some wine.")
case today.Day() > 15:
fmt.Println("Visit a doctor.")
case today.Day() == 25:
fmt.Println("Buy some food.")
default:
fmt.Println("No information available for that day.")
}
}
The switch keyword may be immediately followed by a simple initialization statement where
variables, local to the switch code block, may be declared and initialized.
package main
import (
"fmt"
"time"
)
func main() {
switch today := time.Now(); {
case today.Day() < 5:
fmt.Println("Clean your house.")
case today.Day() <= 10:
fmt.Println("Buy some wine.")
case today.Day() > 15:
fmt.Println("Visit a doctor.")
case today.Day() == 25:
fmt.Println("Buy some food.")
default:
fmt.Println("No information available for that day.")
}
}
A for loop is used for iterating over a sequence (that is either a slice, an array, a map, or a string.
As a language related to the C-family, Golang also supports for loop style control structures.
Golang has no while loop because the for loop serves the same purpose when used with a single
condition.
The for loop is used when you know in advance how many times the script should run.
Consider the following example, display the numbers from 1 to 10 in three different ways.
package main
import "fmt"
func main() {
k := 1
for ; k <= 10; k++ {
fmt.Println(k)
}
k = 1
for k <= 10 {
fmt.Println(k)
k++
}
for k := 1; ; k++ {
fmt.Println(k)
if k == 10 {
break
}
}
}
The for statement supports one additional form that uses the keyword range to iterate over an
expression that evaluates to an array, slice, map, string, or channel
package main
import "fmt"
func main() {
// Example 1
strDict := map[string]string{"Japan": "Tokyo", "China": "Beijing",
"Canada": "Ottawa"}
for index, element := range strDict {
fmt.Println("Index :", index, " Element :", element)
}
// Example 2
for key := range strDict {
fmt.Println(key)
}
// Example 3
for _, value := range strDict {
fmt.Println(value)
}
}
package main
import "fmt"
func main() {
for range "Hello" {
fmt.Println("Hello")
}
}
The for loop runs infinite times unless until we can't break.
package main
import "fmt"
func main() {
i := 5
for {
fmt.Println("Hello")
if i == 10 {
break
}
i++
}
}
Golang Functions
A function is a group of statements that exist within a program for the purpose of performing a
specific task. At a high level, a function takes an input and returns an output.
Function allows you to extract commonly used block of code into a single component.
The single most popular Go function is main(), which is used in every independent Go program.
Creating a Function
A declaration begins with the func keyword, followed by the name you want the function to
have, a pair of parentheses (), and then a block containing the function's code.
The following example has a function with the name SimpleFunction. It takes no parameter and
returns no values.
package main
import "fmt"
func main() {
SimpleFunction()
}
When the above code is compiled and executed, it produces the following result −
Hello World
Information can be passed to functions through arguments. An argument is just like a variable.
Arguments are specified after the function name, inside the parentheses. You can add as many
arguments as you want, just separate them with a comma.
The following example has a function with two arguments of int type. When the add() function
is called, we pass two integer values (e.g. 20,30).
package main
import "fmt"
func main() {
// Passing arguments
add(20, 30)
}
When the above code is compiled and executed, it produces the following result −
50
If the functions with names that start with an uppercase letter will be exported to other packages.
If the function name starts with a lowercase letter, it won't be exported to other packages, but you
can call this function within the same package.
In this example, the add() function takes input of two integer numbers and returns an integer
value with a name of total.
Note the return statement is required when a return value is declared as part of the function's
signature.
package main
import "fmt"
func main() {
// Accepting return value in varaible
sum := add(20, 30)
fmt.Println(sum)
}
The types of input and return value must match with function signature. If we will modify the
above program and pass some string value in argument then program will throw an exception
"cannot use "test" (type string) as type int in argument to add".
Golang allows you to name the return values of a function. We can also name the return value by
defining variables, here a variable total of integer type is defined in the function declaration for
the value that the function returns.
package main
import "fmt"
func rectangle(l int, b int) (area int) {
var parameter int
parameter = 2 * (l + b)
fmt.Println("Parameter: ", parameter)
area = l * b
return // Return statement without specify variable name
}
func main() {
fmt.Println("Area: ", rectangle(20, 30))
}
When the above code is compiled and executed, it produces the following result −
Since the function is declared to return a value of type int, the last logical statement in the
execution flow must be a return statement that returns a value of the declared type.
Functions in Golang can return multiple values, which is a helpful feature in many practical
scenarios.
This example declares a function with two return values and calls it from a main function.
package main
import "fmt"
func main() {
var a, p int
a, p = rectangle(20, 30)
fmt.Println("Area:", a)
fmt.Println("Parameter:", p)
}
Points to remember
A name must begin with a letter, and can have any number of additional letters and numbers.
A function name cannot start with a number.
If the functions with names that start with an uppercase letter will be exported to other
packages. If the function name starts with a lowercase letter, it won't be exported to other
packages, but you can call this function within the same package.
If a name consists of multiple words, each word after the first should be capitalized like this:
empName, EmpAddress, etc.
function names are case-sensitive (car, Car and CAR are three different variables).
Passing the address of variable to the function and the value of a variables modified using
dereferencing inside body of function.
package main
import "fmt"
func main() {
var age = 20
var text = "John"
fmt.Println("Before:", text, age)
update(&age, &text)
You should see the following output when you run the above program −
Anonymous Functions
An anonymous function is a function that was declared without any named identifier to refer to
it. Anonymous functions can accept inputs and return outputs, just as standard functions do.
Assigning function to the variable.
package main
import "fmt"
var (
area = func(l int, b int) int {
return l * b
}
)
func main() {
fmt.Println(area(20, 30))
}
package main
import "fmt"
func main() {
func(l int, b int) {
fmt.Println(l * b)
}(20, 30)
}
package main
import "fmt"
func main() {
fmt.Printf(
"100 (°F) = %.2f (°C)\n",
func(f float64) float64 {
return (f - 32.0) * (5.0 / 9.0)
}(100),
)
}
Anonymous functions can be used for containing functionality that need not be named and possibly for
short-term use.
Closures Functions
Closures are a special case of anonymous functions. Closures are anonymous functions which
access the variables defined outside the body of the function.
Anonymous function accessing the variable defined outside body.
package main
import "fmt"
func main() {
l := 20
b := 30
func() {
var area int
area = l * b
fmt.Println(area)
}()
}
Anonymous function accessing variable on each iteration of loop inside function body.
package main
import "fmt"
func main() {
for i := 10.0; i < 100; i += 10.0 {
rad := func() float64 {
return i * 39.370
}()
fmt.Printf("%.2f Meter = %.2f Inch\n", i, rad)
}
}
Higher order functions are functions that operate on other functions, either by taking them as
arguments or by returning them.
import "fmt"
You should see the following output when you run the above program −
In the program above, the partialSum function returns a sum function that takes two int
arguments and returns a int argument.
import "fmt"
You should see the following output when you run the above program −
In the program above, the squareSum function signature specifying that function returns two
functions and one integer value.
package main
import "fmt"
type First func(int) int
type Second func(int) First
func main() {
// 5*5 + 6*6 + 7*7
fmt.Println(squareSum(5)(6)(7))
}
Golang Functions
A function is a group of statements that exist within a program for the purpose of performing a
specific task. At a high level, a function takes an input and returns an output.
Function allows you to extract commonly used block of code into a single component.
The single most popular Go function is main(), which is used in every independent Go program.
Creating a Function
A declaration begins with the func keyword, followed by the name you want the function to
have, a pair of parentheses (), and then a block containing the function's code.
The following example has a function with the name SimpleFunction. It takes no parameter and
returns no values.
package main
import "fmt"
When the above code is compiled and executed, it produces the following result −
Hello World
Information can be passed to functions through arguments. An argument is just like a variable.
Arguments are specified after the function name, inside the parentheses. You can add as many
arguments as you want, just separate them with a comma.
The following example has a function with two arguments of int type. When the add() function
is called, we pass two integer values (e.g. 20,30).
package main
import "fmt"
func main() {
// Passing arguments
add(20, 30)
}
When the above code is compiled and executed, it produces the following result −
50
If the functions with names that start with an uppercase letter will be exported to other packages.
If the function name starts with a lowercase letter, it won't be exported to other packages, but you
can call this function within the same package.
In this example, the add() function takes input of two integer numbers and returns an integer
value with a name of total.
Note the return statement is required when a return value is declared as part of the function's
signature.
package main
import "fmt"
func main() {
// Accepting return value in varaible
sum := add(20, 30)
fmt.Println(sum)
}
The types of input and return value must match with function signature. If we will modify the
above program and pass some string value in argument then program will throw an exception
"cannot use "test" (type string) as type int in argument to add".
Golang allows you to name the return values of a function. We can also name the return value by
defining variables, here a variable total of integer type is defined in the function declaration for
the value that the function returns.
package main
import "fmt"
area = l * b
return // Return statement without specify variable name
}
func main() {
fmt.Println("Area: ", rectangle(20, 30))
}
When the above code is compiled and executed, it produces the following result −
Since the function is declared to return a value of type int, the last logical statement in the
execution flow must be a return statement that returns a value of the declared type.
Functions in Golang can return multiple values, which is a helpful feature in many practical
scenarios.
This example declares a function with two return values and calls it from a main function.
package main
import "fmt"
func main() {
var a, p int
a, p = rectangle(20, 30)
fmt.Println("Area:", a)
fmt.Println("Parameter:", p)
}
Points to remember
A name must begin with a letter, and can have any number of additional letters and numbers.
A function name cannot start with a number.
If the functions with names that start with an uppercase letter will be exported to other
packages. If the function name starts with a lowercase letter, it won't be exported to other
packages, but you can call this function within the same package.
If a name consists of multiple words, each word after the first should be capitalized like this:
empName, EmpAddress, etc.
function names are case-sensitive (car, Car and CAR are three different variables).
Passing Address to a Function
Passing the address of variable to the function and the value of a variables modified using
dereferencing inside body of function.
package main
import "fmt"
func main() {
var age = 20
var text = "John"
fmt.Println("Before:", text, age)
update(&age, &text)
You should see the following output when you run the above program −
Anonymous Functions
An anonymous function is a function that was declared without any named identifier to refer to
it. Anonymous functions can accept inputs and return outputs, just as standard functions do.
package main
import "fmt"
var (
area = func(l int, b int) int {
return l * b
}
)
func main() {
fmt.Println(area(20, 30))
}
Passing arguments to anonymous functions.
package main
import "fmt"
func main() {
func(l int, b int) {
fmt.Println(l * b)
}(20, 30)
}
package main
import "fmt"
func main() {
fmt.Printf(
"100 (°F) = %.2f (°C)\n",
func(f float64) float64 {
return (f - 32.0) * (5.0 / 9.0)
}(100),
)
}
Anonymous functions can be used for containing functionality that need not be named and possibly for
short-term use.
Closures Functions
Closures are a special case of anonymous functions. Closures are anonymous functions which
access the variables defined outside the body of the function.
package main
import "fmt"
func main() {
l := 20
b := 30
func() {
var area int
area = l * b
fmt.Println(area)
}()
}
Anonymous function accessing variable on each iteration of loop inside function body.
package main
import "fmt"
func main() {
for i := 10.0; i < 100; i += 10.0 {
rad := func() float64 {
return i * 39.370
}()
fmt.Printf("%.2f Meter = %.2f Inch\n", i, rad)
}
}
Higher order functions are functions that operate on other functions, either by taking them as
arguments or by returning them.
import "fmt"
You should see the following output when you run the above program −
In the program above, the partialSum function returns a sum function that takes two int
arguments and returns a int argument.
You should see the following output when you run the above program −
In the program above, the squareSum function signature specifying that function returns two
functions and one integer value.
package main
import "fmt"
func main() {
// 5*5 + 6*6 + 7*7
fmt.Println(squareSum(5)(6)(7))
}
Chapter 13: variadic functions
Variadic Functions
A variadic function is a function that accepts a variable number of arguments. In Golang, it is
possible to pass a varying number of arguments of the same type as referenced in the function
signature. To declare a variadic function, the type of the final parameter is preceded by an
ellipsis, "...", which shows that the function may be called with any number of arguments of this
type. This type of function is useful when you don't know the number of arguments you are
passing to the function, the best example is built-in Println function of the fmt package which is a
variadic function.
In below example we will are going to print s[0] the first and s[3] the forth, argument value
passed to variadicExample() function.
package main
import "fmt"
func main() {
fmt.Println(s[0])
fmt.Println(s[3])
C:\golang\example>
Needs to be precise when running an empty function call, if the code inside of the function
expecting an argument and absence of argument will generate an error "panic: run-time error:
index out of range". In above example you have to pass at least 4 arguments.
The parameter s accepts an infinite number of arguments. The tree-dotted ellipsis tells the
compiler that this string will accept, from zero to multiple values.
package main
import "fmt"
func main() {
variadicExample()
variadicExample("red", "blue")
fmt.Println(s)
C:\golang\example>
In the above example, we have called the function with single and multiple arguments; and
without passing any arguments.
import "fmt"
func main() {
fmt.Println(calculation("Square", 20))
area := 1
if str == "Rectangle" {
area *= val
return area
C:\golang\example>
In the following example, the function signature accepts an arbitrary number of arguments of
type slice.
package main
import (
"fmt"
"reflect"
func main() {
for _, v := range i {
C:\golang\example>
package main
import "fmt"
func first() {
fmt.Println("First")
func second() {
fmt.Println("Second")
func main() {
defer second()
first()
A defer statement is often used with paired operations like open and close, connect and
disconnect, or lock and unlock to ensure that resources are released in all cases, no matter how
complex the control flow. The right place for a defer statement that releases a resource is
immediately after the resource has been successfully acquired.
Below is the example to open a file and perform read/write action on it. In this example there are
often spots where you want to return early.
Without defer
func ReadWrite() bool {
file.Open("file")
if failureX {
return false
if failureY {
return false
return true
A lot of code is repeated here. To overcome this Go has the defer statement. The code above
could be rewritten as follows. This makes the function more readable, shorter and puts the Close
right next to the Open.
With defer
func ReadWrite() bool {
file.Open("file")
// Do your thing
if failureX {
if failureY {
- It keeps our Close call near our Open call so it's easier to understand.
- If our function had multiple return statements (perhaps one in an if and one in an else), Close
will happen before both of them.
- Deferred Functions are run even if a runtime panic occurs.
- Deferred functions are executed in LIFO order, so the above code prints: 4 3 2 1 0.
- You can put multiple functions on the "deferred list", like this example.
package main
import "fmt"
func main() {
Panic is a built-in function that stops the ordinary flow of control and begins panicking. When
the function X calls panic, execution of X stops, any deferred functions in X are executed
normally, and then X returns to its caller. To the caller, X then behaves like a call to panic. The
process continues up the stack until all functions in the current goroutine have returned, at which
point the program crashes. Panics can be initiated by invoking panic directly. They can also be
caused by run-time errors, such as out-of-bounds array accesses.
Not all panics come from the run-time. The built-in panic function may be called directly; it accepts any
value as an argument. A panic is usually the best thing to do when some "impossible" situation happens,
for instance, execution reaches a case that logically can't happen:
package main
import "fmt"
func main() {
var action int
fmt.Println("Enter 1 for Student and 2 for Professional")
fmt.Scanln(&action)
/* Use of Switch Case in Golang */
switch action {
case 1:
fmt.Printf("I am a Student")
case 2:
fmt.Printf("I am a Professional")
default:
panic(fmt.Sprintf("I am a %d",action))
}
fmt.Println("")
fmt.Println("Enter 1 for US and 2 for UK")
fmt.Scanln(&action)
/* Use of Switch Case in Golang */
switch {
case 1:
fmt.Printf("US")
case 2:
fmt.Printf("UK")
default:
panic(fmt.Sprintf("I am a %d",action))
}
}
In above program program will stop execution after first switch-case if user enters any other
value other that 1 or 2.
Recover is a built-in function that regains control of a panicking goroutine. Recover is only useful inside
deferred functions. During normal execution, a call to recover will return nil and have no other effect. If
the current goroutine is panicking, a call to recover will capture the value given to panic and resume
normal execution.
package main
import "fmt"
func main() {
var action int
fmt.Println("Enter 1 for Student and 2 for Professional")
fmt.Scanln(&action)
/* Use of Switch Case in Golang */
switch action {
case 1:
fmt.Printf("I am a Student")
case 2:
fmt.Printf("I am a Professional")
default:
panic(fmt.Sprintf("I am a %d",action))
}
defer func() {
action := recover()
fmt.Println(action)
}()
}
Golang Arrays
An array is a data structure that consists of a collection of elements of a single type or simply
you can say a special variable, which can hold more than one value at a time. The values an array
holds are called its elements or items. An array holds a specific number of elements, and it
cannot grow or shrink. Different data types can be handled as elements in arrays such as Int,
String, Boolean, and others. The index of the first element of any dimension of an array is 0, the
index of the second element of any array dimension is 1, and so on.
To declare an array you need to specify the number of elements it holds in square brackets ([]),
followed by the type of elements the array holds.
package main
import (
"fmt"
"reflect"
)
func main() {
var intArray [5]int
var strArray [5]string
fmt.Println(reflect.ValueOf(intArray).Kind())
fmt.Println(reflect.ValueOf(strArray).Kind())
}
array
array
How to assign and access array element values in Go?
You access or assign the array elements by referring to the index number. The index is specified
in square brackets.
package main
import "fmt"
func main() {
var theArray [3]string
theArray[0] = "India" // Assign a value to the first element
theArray[1] = "Canada" // Assign a value to the second element
theArray[2] = "Japan" // Assign a value to the third element
You can initialize an array with pre-defined values using an array literal. An array literal have the
number of elements it will hold in square brackets, followed by the type of its elements. This is
followed by a list of initial values separated by commas of each element inside the curly braces.
package main
import "fmt"
func main() {
x := [5]int{10, 20, 30, 40, 50} // Intialized with values
var y [5]int = [5]int{10, 20, 30} // Partial assignment
fmt.Println(x)
fmt.Println(y)
}
[10 20 30 40 50]
[10 20 30 0 0]
When we use ... instead of specifying the length. The compiler can identify the length of an
array, based on the elements specified in the array declaration.
package main
import (
"fmt"
"reflect"
)
func main() {
x := [...]int{10, 20, 30}
fmt.Println(reflect.ValueOf(x).Kind())
fmt.Println(len(x))
}
array
3
When an array declare using an array literal, values can be initialize for specific elements.
A value of 10 is assigned to the second element (index 1) and a value of 30 is assigned to the fourth
element (index 3).
package main
import "fmt"
func main() {
x := [5]int{1: 10, 3: 30}
fmt.Println(x)
}
[0 10 0 30 0]
package main
import "fmt"
func main() {
intArray := [5]int{10, 20, 30, 40, 50}
fmt.Println("\n---------------Example 1--------------------\n")
for i := 0; i < len(intArray); i++ {
fmt.Println(intArray[i])
}
fmt.Println("\n---------------Example 2--------------------\n")
for index, element := range intArray {
fmt.Println(index, "=>", element)
}
fmt.Println("\n---------------Example 3--------------------\n")
for _, value := range intArray {
fmt.Println(value)
}
j := 0
fmt.Println("\n---------------Example 4--------------------\n")
for range intArray {
fmt.Println(intArray[j])
j++
}
}
You can create copy of an array, by assigning an array to a new variable either by value or
reference.
package main
import "fmt"
func main() {
strArray1[0] = "Canada"
To determine if a specific element exist in an array, we need to iterate each array element using
for loop and check using if condition.
package main
import (
"fmt"
"reflect"
)
func main() {
strArray := [5]string{"India", "Canada", "Japan", "Germany", "Italy"}
fmt.Println(itemExists(strArray, "Canada"))
fmt.Println(itemExists(strArray, "Africa"))
}
if arr.Kind() != reflect.Array {
panic("Invalid data-type")
}
return false
}
true
false
A value of 10 is assigned to the second element (index 1) and a value of 30 is assigned to the fourth
element (index 3).
package main
import "fmt"
func main() {
countries := [...]string{"India", "Canada", "Japan", "Germany",
"Italy"}
Golang Slices
A slice is a flexible and extensible data structure to implement and manage collections of data.
Slices are made up of multiple elements, all of the same type. A slice is a segment of dynamic
arrays that can grow and shrink as you see fit. Like arrays, slices are index-able and have a
length. Slices have a capacity and length property.
To declare the type for a variable that holds a slice, use an empty pair of square brackets,
followed by the type of elements the slice will hold.
package main
import (
"fmt"
"reflect"
)
func main() {
var intSlice []int
var strSlice []string
fmt.Println(reflect.ValueOf(intSlice).Kind())
fmt.Println(reflect.ValueOf(strSlice).Kind())
}
Creating empty slice of Integer and String type.
slice
slice
Slice can be created using the built-in function make. When you use make, one option you have
is to specify the length of the slice. When you just specify the length, the capacity of the slice is
the same.
package main
import (
"fmt"
"reflect"
)
func main() {
var intSlice = make([]int, 10) // when length and capacity is
same
var strSlice = make([]string, 10, 20) // when length and capacity is
different
A slice literal contain empty brackets followed by the type of elements the slice will hold, and a
list of the initial values each element will have in curly braces.
package main
import "fmt"
func main() {
var intSlice = []int{10, 20, 30, 40}
var strSlice = []string{"India", "Canada", "Japan"}
A slice can be declare using new keyword followed by capacity in square brackets then type of
elements the slice will hold.
package main
import (
"fmt"
"reflect"
)
func main() {
var intSlice = new([50]int)[0:10]
fmt.Println(reflect.ValueOf(intSlice).Kind())
fmt.Printf("intSlice \tLen: %v \tCap: %v\n", len(intSlice),
cap(intSlice))
fmt.Println(intSlice)
}
slice
intSlice Len: 10 Cap: 50
[0 0 0 0 0 0 0 0 0 0]
To add an item to the end of the slice, use the append() method.
package main
import "fmt"
func main() {
a := make([]int, 2, 5)
a[0] = 10
a[1] = 20
fmt.Println("Slice A:", a)
fmt.Printf("Length is %d Capacity is %d\n", len(a), cap(a))
a = append(a, 30, 40, 50, 60, 70, 80, 90)
fmt.Println("Slice A after appending data:", a)
fmt.Printf("Length is %d Capacity is %d\n", len(a), cap(a))
}
If there's sufficient capacity in the underlying slice, the element is placed after the last element and the
length get incremented. However, if there is not sufficient capacity, a new slice is created, all of the
existing elements are copied over, the new element is added onto the end, and the new slice is returned.
package main
import "fmt"
func main() {
var intSlice = []int{10, 20, 30, 40}
fmt.Println(intSlice[0])
fmt.Println(intSlice[1])
fmt.Println(intSlice[0:4])
}
package main
import "fmt"
func main() {
var strSlice = []string{"India", "Canada", "Japan"}
fmt.Println(strSlice)
strSlice[2] = "Germany"
fmt.Println(strSlice)
}
[India Canada Japan]
[India Canada Germany]
How to delete an element from a Slice in Golang?
package main
import "fmt"
func main() {
var strSlice = []string{"India", "Canada", "Japan", "Germany",
"Italy"}
fmt.Println(strSlice)
strSlice = RemoveIndex(strSlice, 3)
fmt.Println(strSlice)
}
The built-in copy function is used to copy data from one slice to another.
package main
import "fmt"
func main() {
a := []int{5, 6, 7} // Create a smaller slice
fmt.Printf("[Slice:A] Length is %d Capacity is %d\n", len(a), cap(a))
package main
import "fmt"
func main() {
var countries = []string{"india", "japan", "canada", "australia",
"russia"}
fmt.Println(countries[:])
fmt.Println(countries[0:])
fmt.Println(countries[0:len(countries)])
}
Countries: [india japan canada australia russia]
:2 [india japan]
1:3 [japan canada]
2: [canada australia russia]
2:5 [canada australia russia]
0:3 [india japan canada]
Last element: russia
Last element: russia
Last element: [russia]
All elements: [india japan canada australia russia]
Last two elements: [australia russia]
Last two elements: [australia russia]
[india japan canada australia russia]
[india japan canada australia russia]
[india japan canada australia russia]
How to Iterate Over a Slice in Golang?
You can loop through the list items by using a for loop.
package main
import "fmt"
func main() {
var strSlice = []string{"India", "Canada", "Japan", "Germany",
"Italy"}
fmt.Println("\n---------------Example 1 --------------------\n")
for index, element := range strSlice {
fmt.Println(index, "--", element)
}
fmt.Println("\n---------------Example 2 --------------------\n")
for _, value := range strSlice {
fmt.Println(value)
}
j := 0
fmt.Println("\n---------------Example 3 --------------------\n")
for range strSlice {
fmt.Println(strSlice[j])
j++
}
}
package main
import "fmt"
func main() {
var slice1 = []string{"india", "japan", "canada"}
var slice2 = []string{"australia", "russia"}
To determine if a specified item is present in a slice iterate slice item and check using if
condition.
package main
import (
"fmt"
"reflect"
)
func main() {
var strSlice = []string{"India", "Canada", "Japan", "Germany",
"Italy"}
fmt.Println(itemExists(strSlice, "Canada"))
fmt.Println(itemExists(strSlice, "Africa"))
}
if s.Kind() != reflect.Slice {
panic("Invalid data-type")
}
return false
}
Chapter 18
Golang Maps
In this tutorial you will learn what is a map data type and when to use it in Golang.
A map is a data structure that provides you with an unordered collection of key/value pairs (maps
are also sometimes called associative arrays in Php, hash tables in Java, or dictionaries in
Python). Maps are used to look up a value by its associated key. You store values into the map
based on a key.
The strength of a map is its ability to retrieve data quickly based on the key. A key works like an
index, pointing to the value you associate with that key.
A map is implemented using a hash table, which is providing faster lookups on the data element
and you can easily retrieve a value by providing the key. Maps are unordered collections, and
there's no way to predict the order in which the key/value pairs will be returned. Every iteration
over a map could return a different order.
Map initialization
In Golang maps are written with curly brackets, and they have keys and values. Creating an
instance of a map data type.
package main
import "fmt"
func main() {
fmt.Println(employee)
}
package main
import "fmt"
func main() {
var employee = map[string]int{}
fmt.Println(employee) // map[]
fmt.Printf("%T\n", employee) // map[string]int
}
The make function takes as argument the type of the map and it returns an initialized map.
package main
import "fmt"
func main() {
var employee = make(map[string]int)
employee["Mark"] = 10
employee["Sandy"] = 20
fmt.Println(employee)
employeeList := make(map[string]int)
employeeList["Mark"] = 10
employeeList["Sandy"] = 20
fmt.Println(employeeList)
}
Map Length
To determine how many items (key-value pairs) a map has, use built-in len() function.
package main
import "fmt"
func main() {
var employee = make(map[string]int)
employee["Mark"] = 10
employee["Sandy"] = 20
// Empty Map
employeeList := make(map[string]int)
fmt.Println(len(employee)) // 2
fmt.Println(len(employeeList)) // 0
}
Accessing Items
You can access the items of a map by referring to its key name, inside square brackets.
package main
import "fmt"
func main() {
var employee = map[string]int{"Mark": 10, "Sandy": 20}
fmt.Println(employee["Mark"])
}
Adding Items
Adding an item to the map is done by using a new index key and assigning a value to it.
package main
import "fmt"
func main() {
var employee = map[string]int{"Mark": 10, "Sandy": 20}
fmt.Println(employee) // Initial Map
fmt.Println(employee)
}
Update Values
You can update the value of a specific item by referring to its key name.
package main
import "fmt"
func main() {
var employee = map[string]int{"Mark": 10, "Sandy": 20}
fmt.Println(employee) // Initial Map
Delete Items
The built-in delete function deletes an item from a given map associated with the provided key.
package main
import "fmt"
func main() {
var employee = make(map[string]int)
employee["Mark"] = 10
employee["Sandy"] = 20
employee["Rocky"] = 30
employee["Josef"] = 40
fmt.Println(employee)
delete(employee, "Mark")
fmt.Println(employee)
}
Iterate over a Map
The for…range loop statement can be used to fetch the index and element of a map.
package main
import "fmt"
func main() {
var employee = map[string]int{"Mark": 10, "Sandy": 20,
"Rocky": 30, "Rajiv": 40, "Kate": 50}
for key, element := range employee {
fmt.Println("Key:", key, "=>", "Element:", element)
}
}
Truncate Map
package main
func main() {
var employee = map[string]int{"Mark": 10, "Sandy": 20,
"Rocky": 30, "Rajiv": 40, "Kate": 50}
// Method - I
for k := range employee {
delete(employee, k)
}
// Method - II
employee = make(map[string]int)
}
A Keys slice created to store keys value of map and then sort the slice. The sorted slice used to
print values of map in key order.
package main
import (
"fmt"
"sort"
)
func main() {
unSortedMap := map[string]int{"India": 20, "Canada": 70, "Germany":
15}
To sort the key values of a map, you need to store them in Slice and then sort the slice.
package main
import (
"fmt"
"sort"
)
func main() {
unSortedMap := map[string]int{"India": 20, "Canada": 70, "Germany":
15}
Merge Maps
The keys and values of second map getting added in first map.
package main
import "fmt"
func main() {
first := map[string]int{"a": 1, "b": 2, "c": 3}
second := map[string]int{"a": 1, "e": 5, "c": 3, "d": 4}
fmt.Println(first)
}
Chapter
Golang Struct
A struct (short for "structure") is a collection of data fields with declared data types. Golang has
the ability to declare and create own data types by combining one or more types, including both
built-in and user-defined types. Each data field in a struct is declared with a known type, which
could be a built-in type or another user-defined type.
Structs are the only way to create concrete user-defined types in Golang. Struct types are
declared by composing a fixed set of unique fields. Structs can improve modularity and allow to
create and pass complex data structures around the system. You can also consider Structs as a
template for creating a data record, like an employee record or an e-commerce product.
The declaration starts with the keyword type, then a name for the new struct, and finally the
keyword struct. Within the curly brackets, a series of data fields are specified with a name and a
type.
A struct type rectangle is declared that has three data fields of different data-types. Here, struct
used without instantiate a new instance of that type.
package main
import "fmt"
type rectangle struct {
length float64
breadth float64
color string
}
func main() {
fmt.Println(rectangle{10.5, 25.10, "red"})
}
The rectangle struct and its fields are not exported to other packages because identifiers are
started with an lowercase letter. In Golang, identifiers are exported to other packages if the name
starts with an uppercase letter, otherwise the accessibility will be limited within the package only.
The var keyword initializes a variable rect. Using dot notation, values are assigned to the struct
fields.
package main
import "fmt"
geometry struct {
area int
perimeter int
}
}
func main() {
var rect rectangle // dot notation
rect.length = 10
rect.breadth = 20
rect.color = "Green"
fmt.Println(rect)
fmt.Println("Area:\t", rect.geometry.area)
fmt.Println("Perimeter:", rect.geometry.perimeter)
}
The struct is printed to the terminal, showing the values have been assigned.
Creating a Struct Instance Using a Struct Literal
Creates an instance of rectangle struct by using a struct literal and assigning values to the fields
of the struct.
package main
import "fmt"
func main() {
var rect1 = rectangle{10, 20, "Green"}
fmt.Println(rect1)
An instance of a struct can also be created with the new keyword. It is then possible to assign
data values to the data fields using dot notation.
package main
import "fmt"
func main() {
rect1 := new(rectangle) // rect1 is a pointer to an instance of
rectangle
rect1.length = 10
rect1.breadth = 20
rect1.color = "Green"
fmt.Println(rect1)
Two instances of the rectangle struct are instantiated, rect1 points to the address of the
instantiated struct and rect2 is the name of a struct it represents.
Creates an instance of rectangle struct by using a pointer address operator is denoted by &
symbol.
package main
import "fmt"
func main() {
var rect1 = &rectangle{10, 20, "Green"} // Can't skip any value
fmt.Println(rect1)
Struct can be nested by creating a Struct type using other Struct types as the type for the fields of
Struct. Nesting one struct within another can be a useful way to model more complex structures.
package main
import "fmt"
func main() {
e := Employee{
FirstName: "Mark",
LastName: "Jones",
Email: "mark@gmail.com",
Age: 25,
MonthlySalary: []Salary{
Salary{
Basic: 15000.00,
HRA: 5000.00,
TA: 2000.00,
},
Salary{
Basic: 16000.00,
HRA: 5000.00,
TA: 2100.00,
},
Salary{
Basic: 17000.00,
HRA: 5000.00,
TA: 2200.00,
},
},
}
fmt.Println(e.FirstName, e.LastName)
fmt.Println(e.Age)
fmt.Println(e.Email)
fmt.Println(e.MonthlySalary[0])
fmt.Println(e.MonthlySalary[1])
fmt.Println(e.MonthlySalary[2])
}
During the definition of a struct type, optional string values may be added to each field
declaration.
package main
import (
"fmt"
"encoding/json"
)
func main() {
json_string := `
{
"firstname": "Rocky",
"lastname": "Sting",
"city": "London"
}`
emp1 := new(Employee)
json.Unmarshal([]byte(json_string), emp1)
fmt.Println(emp1)
emp2 := new(Employee)
emp2.FirstName = "Ramesh"
emp2.LastName = "Soni"
emp2.City = "Mumbai"
jsonStr, _ := json.Marshal(emp2)
fmt.Printf("%s\n", jsonStr)
}
The tags are represented as raw string values (wrapped within a pair of ``) and ignored by normal
code execution.
You can also add methods to struct types using a method receiver. A method EmpInfo is added
to the Employee struct.
package main
import "fmt"
func main() {
e := Employee{
FirstName: "Mark",
LastName: "Jones",
Email: "mark@gmail.com",
Age: 25,
MonthlySalary: []Salary{
Salary{
Basic: 15000.00,
HRA: 5000.00,
TA: 2000.00,
},
Salary{
Basic: 16000.00,
HRA: 5000.00,
TA: 2100.00,
},
Salary{
Basic: 17000.00,
HRA: 5000.00,
TA: 2200.00,
},
},
}
fmt.Println(e.EmpInfo())
}
Method of assigning a custom default value can be achieve by using constructor function.
Instead of creating a struct directly, the Info function can be used to create an Employee struct
with a custom default value for the Name and Age field.
package main
import "fmt"
func main() {
emp1 := Employee{Name: "Mr. Fred"}
emp1.Info()
fmt.Println(emp1)
This is a technique rather than something that is part of the Golang specification.
package main
import (
"fmt"
"reflect"
)
func main() {
var rect1 = rectangle{10, 20, "Green"}
fmt.Println(reflect.TypeOf(rect1)) // main.rectangle
fmt.Println(reflect.ValueOf(rect1).Kind()) // struct
rect3 := new(rectangle)
fmt.Println(reflect.TypeOf(rect3)) // *main.rectangle
fmt.Println(reflect.ValueOf(rect3).Kind()) // ptr
package main
import "fmt"
func main() {
var rect1 = rectangle{10, 20, "Green"}
rect2 := rectangle{length: 20, breadth: 10, color: "Red"}
if rect1 == rect2 {
fmt.Println("True")
} else {
fmt.Println("False")
}
rect3 := new(rectangle)
var rect4 = &rectangle{}
if rect3 == rect4 {
fmt.Println("True")
} else {
fmt.Println("False")
}
}
r2 will be the same as r1, it is a copy of r1 rather than a reference to it. Any changes made to r2
will not be applied to r1 and vice versa. When r3 is updated, the underlying memory that is
assigned to r1 is updated.
package main
import "fmt"
type rectangle struct {
length float64
breadth float64
color string
}
func main() {
r1 := rectangle{10, 20, "Green"}
fmt.Println(r1)
r2 := r1
r2.color = "Pink"
fmt.Println(r2)
r3 := &r1
r3.color = "Red"
fmt.Println(r3)
fmt.Println(r1)
}
{10 20 Green}
{10 20 Pink}
&{10 20 Red}
{10 20 Red}
As both r1 and r3 both reference the same underlying memory, their values are the same. Printing
the values of r3 and r1 shows that the values are the same.
Chapter ….
Golang Interface
Interface describes all the methods of a method set and provides the signatures for each method.
To create interface use interface keyword, followed by curly braces containing a list of method
names, along with any parameters or return values the methods are expected to have.
An interfaces act as a blueprint for method sets, they must be implemented before being used.
Type that satisfies an interface is said to implement it.
Define Type that Satisfies an Interface
Defines an interface type named Employee with two methods. Then it defines a type named
Emp that satisfies Employee.
package main
import "fmt"
func main() {
var e1 Employee
e1 = Emp(1)
e1.PrintName("John Doe")
fmt.Println("Employee Salary:", e1.PrintSalary(25000, 5))
}
If a type has all the methods declared in an interface, then no further declarations needed
explicitly to say that Emp satisfies Employee.
Declares an e1 variable with Employee as its type, then creates a Emp value and assigns it to e1.
Interfaces allows any user-defined type to satisfy multiple interface types at once.
Using Type Assertion you can get a value of a concrete type back and you can call methods on it
that are defined on other interface, but aren't part of the interface satisfying.
package main
import "fmt"
func main() {
var p Polygons = Pentagon(50)
p.Perimeter()
var o Pentagon = p.(Pentagon)
o.NumberOfSide()
When a user-defined type implements the set of methods declared by an interface type, values of
the user-defined type can be assigned to values of the interface type. This assignment stores the
value of the user-defined type into the interface value. When a method call is made against an
interface value, the equivalent method for the stored user-defined value will be executed. Since
any user-defined type can implement any interface, method calls against an interface value are
polymorphic in nature. The user-defined type in this relationship is often referred as concrete
type.
Two or more interfaces can have one or more common method in list of method sets. Here,
Structure is a common method between two interfaces Vehicle and Human.
package main
import "fmt"
func main() {
var bmw Vehicle
bmw = Car("World Top Brand")
When the above code is compiled and executed, it produces the following result −
The Print() methods accept a receiver pointer. Hence, the interface must also accept a receiver
pointer.
If a method accepts a type value, then the interface must receive a type value; if a method has a
pointer receiver, then the interface must receive the address of the variable of the respective type.
package main
import "fmt"
func main() {
var b Book // Declare instance of Book
var m Magazine // Declare instance of
Magazine
b.Assign("Jack Rabbit", "Book of Rabbits") // Assign values to b via
method
m.Assign("Rabbit Weekly", 26) // Assign values to m via
method
The type interface{} is known as the empty interface, and it is used to accept values of any type.
The empty interface doesn't have any methods that are required to satisfy it, and so every type
satisfies it.
package main
import "fmt"
func main() {
var manyType interface{}
manyType = 100
fmt.Println(manyType)
manyType = 200.50
fmt.Println(manyType)
manyType = "Germany"
fmt.Println(manyType)
The manyType variable is declared to be of the type interface{} and it is able to be assigned
values of different types. The printType() function takes a parameter of the type interface{},
hence this function can take the values of any valid type.
When the above code is compiled and executed, it produces the following result −
go run main.go
100
200.5
Germany
Go programming language
[india japan canada australia russia]
map[Mark:10 Sandy:20]
[Japan Australia Germany]
Polymorphism
Polymorphism is the ability to write code that can take on different behavior through the
implementation of types.
We have the declaration of a structs named Pentagon, Hexagon, Octagon and Decagon with the
implementation of the Geometry interface.
package main
import (
"fmt"
)
g := [...]Geometry{p, h, o, d}
for _, i := range g {
fmt.Println(Parameter(i, 5))
}
}
When the above code is compiled and executed, it produces the following result −
We have our polymorphic Edges functions that accepts values that implement the Geometry
interface. Using polymorphic approach the method created here Parameter is used by each
concrete type value that's passed in.
Interface Embedding
Interfaces may embed other interfaces, this behavior is an aspect of interface polymorphism
which is known as ad hoc polymorphism.
package main
import "fmt"
func main() {
p := new(Pentagon)
h := new(Hexagon)
o := new(Octagon)
d := new(Decagon)
polygons := [...]Polygons{p, h, o, d}
for i := range polygons {
fmt.Println(polygons[i].Edges())
}
}
When one type is embedded into another type, the methods of the embedded type are available to
the embedding type. The method or methods of the embedded interface are accessible to the
embedding interface.
Chapter …
Golang Goroutines
Concurrency in Golang is the ability for functions to run independent of each other. Goroutines
are functions that are run concurrently. Golang provides Goroutines as a way to handle
operations concurrently.
To run a function as a goroutine, call that function prefixed with the go statement. Here is the
example code block:
sum() // A normal function call that executes sum synchronously and waits
for completing it
go sum() // A goroutine that executes sum asynchronously and doesn't wait for
completing it
The go keyword makes the function call to return immediately, while the function starts running
in the background as a goroutine and the rest of the program continues its execution. The main
function of every Golang program is started using a goroutine, so every Golang program runs at
least one goroutine.
Creating Goroutines
Added the go keyword before each call of function responseSize. The three responseSize
goroutines starts up concurrently and three calls to http.Get are made concurrently as well. The
program doesn't wait until one response comes back before sending out the next request. As a
result the three response sizes are printed much sooner using goroutines.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
)
func main() {
go responseSize("https://www.golangprograms.com")
go responseSize("https://coderwall.com")
go responseSize("https://stackoverflow.com")
time.Sleep(10 * time.Second)
}
We have added a call to time.Sleep in the main function which prevents the main goroutine from
exiting before the responseSize goroutines can finish. Calling time.Sleep(10 * time.Second) will
make the main goroutine to sleep for 10 seconds.
You may see the following output when you run the above program −
The WaitGroup type of sync package, is used to wait for the program to finish all goroutines
launched from the main function. It uses a counter that specifies the number of goroutines, and
Wait blocks the execution of the program until the WaitGroup counter is zero.
The Done method of WaitGroup is scheduled using a defer statement to decrement the
WaitGroup counter.
The Wait method of the WaitGroup type waits for the program to finish all goroutines.
The Wait method is called inside the main function, which blocks execution until the WaitGroup
counter reaches the value of zero and ensures that all goroutines are executed.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"sync"
)
func main() {
// Add a count of three, one for each goroutine.
wg.Add(3)
fmt.Println("Start Goroutines")
go responseSize("https://www.golangprograms.com")
go responseSize("https://stackoverflow.com")
go responseSize("https://coderwall.com")
You may see the following output when you run the above program −
The most natural way to fetch a value from a goroutine is channels. Channels are the pipes that
connect concurrent goroutines. You can send values into channels from one goroutine and
receive those values into another goroutine or in a synchronous function.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"sync"
)
func main() {
nums := make(chan int) // Declare a unbuffered channel
wg.Add(1)
go responseSize("https://www.golangprograms.com", nums)
fmt.Println(<-nums) // Read the value from unbuffered channel
wg.Wait()
close(nums) // Closes the channel
}
You may see the following output when you run the above program −
Using channels we can play and pause execution of goroutine. A channel handles this
communication by acting as a conduit between goroutines.
package main
import (
"fmt"
"sync"
"time"
)
var i int
func work() {
time.Sleep(250 * time.Millisecond)
i++
fmt.Println(i)
}
func main() {
var wg sync.WaitGroup
wg.Add(1)
command := make(chan string)
go routine(command, &wg)
time.Sleep(1 * time.Second)
command <- "Pause"
time.Sleep(1 * time.Second)
command <- "Play"
time.Sleep(1 * time.Second)
command <- "Stop"
wg.Wait()
}
You can see the following output when you run the above program −
1
2
3
4
Pause
Play
5
6
7
8
9
Stop
Race conditions occur due to unsynchronized access to shared resource and attempt to read and
write to that resource at the same time.
Atomic functions provide low-level locking mechanisms for synchronizing access to integers
and pointers. Atomic functions generally used to fix the race condition.
The functions in the atomic under sync packages provides support to synchronize goroutines by
locking access to shared resources.
package main
import (
"fmt"
"runtime"
"sync"
"sync/atomic"
)
var (
counter int32 // counter is a variable incremented by all
goroutines.
wg sync.WaitGroup // wg is used to wait for the program to
finish.
)
func main() {
wg.Add(3) // Add a count of two, one for each goroutine.
go increment("Python")
go increment("Java")
go increment("Golang")
The AddInt32 function from the atomic package synchronizes the adding of integer values by
enforcing that only one goroutine can perform and complete this add operation at a time. When
goroutines attempt to call any atomic function, they're automatically synchronized against the
variable that's referenced.
You can see the following output when you run the above program −
C:\Golang\goroutines>
Note if you replace the code line atomic.AddInt32(&counter, 1) with counter++, then you will
see the below output-
C:\Golang\goroutines>
A mutex is used to create a critical section around code that ensures only one goroutine at a time
can execute that code section.
package main
import (
"fmt"
"sync"
)
var (
counter int32 // counter is a variable incremented by all
goroutines.
wg sync.WaitGroup // wg is used to wait for the program to
finish.
mutex sync.Mutex // mutex is used to define a critical section
of code.
)
func main() {
wg.Add(3) // Add a count of two, one for each goroutine.
go increment("Python")
go increment("Go Programming Language")
go increment("Java")
A critical section defined by the calls to Lock() and Unlock() protects the actions against the
counter variable and reading the text of name variable. You can see the following output when
you run the above program −
C:\Golang\goroutines>
Chapter ……
There are two types of channels based on their behavior of data exchange: unbuffered channels
and buffered channels. An unbuffered channel is used to perform synchronous communication
between goroutines while a buffered channel is used for perform asynchronous communication.
An unbuffered channel provides a guarantee that an exchange between two goroutines is
performed at the instant the send and receive take place. A buffered channel has no such
guarantee.
A channel is created by the make function, which specifies the chan keyword and a
channel's element type.
Here is the code block that creates an unbuffered and buffered channel:
Unbuffered := make(chan int) // Unbuffered channel of integer type
The use of the built-in function make to create both an unbuffered and buffered channel. The first
argument to make requires the keyword chan and then the type of data the channel will allow to
be exchanged.
Here is the code block to send a value into a channel requires the use of the <- operator:
goroutine1 := make(chan string, 5) // Buffered channel of strings.
A goroutine1 channel of type string that contains a buffer of 5 values. Then we send the string
"Australia" through the channel.
The <- operator is attached to the left side of the channel variable(goroutine1), to receive a value
from a channel.
Unbuffered channels
In unbuffered channel there is no capacity to hold any value before it's received. In this type of
channels both a sending and receiving goroutine to be ready at the same instant before any send
or receive operation can complete. If the two goroutines aren't ready at the same instant, the
channel makes the goroutine that performs its respective send or receive operation first wait.
Synchronization is fundamental in the interaction between the send and receive on the channel.
One can't happen without the other.
Buffered channels
In buffered channel there is a capacity to hold one or more values before they're received. In this
types of channels don't force goroutines to be ready at the same instant to perform sends and
receives. There are also different conditions for when a send or receive does block. A receive will
block only if there's no value in the channel to receive. A send will block only if there's no
available buffer to place the value being sent.
package main
import (
"fmt"
"math/rand"
"sync"
"time"
func main(){
rand.Seed(time.Now().Unix())
// Create a buffered channel to manage the employee vs project load.
goRoutine.Add(5)
go employee(projects, i)
close(projects)
goRoutine.Wait()
defer goRoutine.Done()
for {
if result==false {
sleep := rand.Int63n(50)
time.Sleep(time.Duration(sleep) * time.Millisecond)
fmt.Println("\nTime to sleep",sleep,"ms\n")
Every time you run this program the output for this program will be different this is because of
the random nature of the program and the Go scheduler.
In above program, a buffered channel of type string is created with a capacity of 10. WaitGroup
is given the count of 5, one for each goroutine. 10 strings are sent into the channel to simulate or
replicate project for the goroutines. Once the last string is sent into the channel, the channel is
going to be closed and the main function waits for all the project to be completed.
Chapter …
Golang Concurrency
Concurrency is an ability of a program to do multiple things at the same time. This means a
program that have two or more tasks that run individually of each other, at about the same time,
but remain part of the same program. Concurrency is very important in modern software, due to
the need to execute independent pieces of code as fast as possible without disturbing the overall
flow of the program.
Concurrency in Golang is the ability for functions to run independent of each other. A goroutine
is a function that is capable of running concurrently with other functions. When you create a
function as a goroutine, it has been treated as an independent unit of work that gets scheduled
and then executed on an available logical processor. The Golang runtime scheduler has feature to
manages all the goroutines that are created and need processor time. The scheduler binds
operating system's threads to logical processors in order to execute the goroutines. By sitting on
top of the operating system, scheduler controls everything related to which goroutines are
running on which logical processors at any given time.
Popular programming languages such as Java and Python implement concurrency by using
threads. Golang has built-in concurrency constructs: goroutines and channels. Concurrency in
Golang is cheap and easy. Goroutines are cheap, lightweight threads. Channels, are the conduits
that allow for communication between goroutines.
Communicating Sequential Processes, or CSP for short, is used to describe how systems that
feature multiple concurrent models should interact with one another. It typically relies heavily on
using channels as a medium for passing messages between two or more concurrent processes,
and is the underlying mantra of Golang.
Goroutines — A goroutine is a function that runs independently of the function that started it.
Channels — A channel is a pipeline for sending and receiving data. Channels provide a way for
one goroutine to send structured data to another.
Concurrency and parallelism comes into the picture when you are examining for multitasking
and they are often used interchangeably, concurrent and parallel refer to related but different
things.
Concurrency - Concurrency is about to handle numerous tasks at once. This means that you are
working to manage numerous tasks done at once in a given period of time. However, you will
only be doing a single task at a time. This tends to happen in programs where one task is waiting
and the program determines to drive another task in the idle time. It is an aspect of the problem
domain — where your program needs to handle numerous simultaneous events.
Parallelism - Parallelism is about doing lots of tasks at once. This means that even if we have
two tasks, they are continuously working without any breaks in between them. It is an aspect of
the solution domain — where you want to make your program faster by processing different
portions of the problem in parallel.
A concurrent program has multiple logical threads of control. These threads may or may not run
in parallel. A parallel program potentially runs more quickly than a sequential program by
executing different parts of the computation simultaneously (in parallel). It may or may not have
more than one logical thread of control.
Illustration of the dining philosophers problem in Golang
Five silent philosophers sit at a round table with bowls of spaghetti. Forks are placed between
each pair of adjacent philosophers. Each philosopher must alternately think and eat. However, a
philosopher can only eat spaghetti when they have both left and right forks. Each fork can be
held by only one philosopher and so a philosopher can use the fork only if it is not being used by
another philosopher. After an individual philosopher finishes eating, they need to put down both
forks so that the forks become available to others. A philosopher can take the fork on their right
or the one on their left as they become available, but cannot start eating before getting both forks.
Eating is not limited by the remaining amounts of spaghetti or stomach space; an infinite supply
and an infinite demand are assumed. The problem is how to design a discipline of behavior (a
concurrent algorithm) such that no philosopher will starve; i.e., each can forever continue to
alternate between eating and thinking, assuming that no philosopher can know when others may
want to eat or think.
package main
import (
"hash/fnv"
"log"
"math/rand"
"os"
"sync"
"time"
)
func main() {
fmt.Println("Table empty")
dining.Add(5)
fork0 := &sync.Mutex{}
forkLeft := fork0
for i := 1; i < len(ph); i++ {
forkRight := &sync.Mutex{}
go diningProblem(ph[i], forkLeft, forkRight)
forkLeft = forkRight
}
go diningProblem(ph[0], fork0, forkLeft)
dining.Wait() // wait for philosphers to finish
fmt.Println("Table empty")
}
Table empty
Mark seated
Mark Hungry
Mark Eating
..................
..................
Haris Thinking
Haris Satisfied
Haris Left the table
Table empty
package main
import (
"log"
"math/rand"
"sync"
"time"
)
var (
partList = []string{"A", "B", "C", "D"}
nAssemblies = 3
wg sync.WaitGroup
)
func main() {
rand.Seed(time.Now().UnixNano())
for c := 1; c <= nAssemblies; c++ {
log.Println("begin assembly cycle", c)
wg.Add(len(partList))
for _, part := range partList {
go worker(part)
}
wg.Wait()
log.Println("assemble. cycle", c, "complete")
}
}
2019/07/15 16:10:32 begin assembly cycle 1
2019/07/15 16:10:32 D worker begins part
2019/07/15 16:10:32 A worker begins part
2019/07/15 16:10:32 B worker begins part
........
2019/07/15 16:10:32 D worker completes part
2019/07/15 16:10:32 C worker completes part
2019/07/15 16:10:32 assemble. cycle 3 complete
The problem describes two processes, the producer and the consumer, who share a common,
fixed-size buffer used as a queue. The producer's job is to generate data, put it into the buffer, and
start again. At the same time, the consumer is consuming the data (i.e., removing it from the
buffer), one piece at a time. The problem is to make sure that the producer won't try to add data
into the buffer if it's full and that the consumer won't try to remove data from an empty buffer.
The solution for the producer is to either go to sleep or discard data if the buffer is full. The next
time the consumer removes an item from the buffer, it notifies the producer, who starts to fill the
buffer again. In the same way, the consumer can go to sleep if it finds the buffer empty. The next
time the producer puts data into the buffer, it wakes up the sleeping consumer.
package main
import (
"flag"
"fmt"
"log"
"os"
"runtime"
"runtime/pprof"
)
// Producer definition
type Producer struct {
msgs *chan int
done *chan bool
}
func main() {
// profile flags
cpuprofile := flag.String("cpuprofile", "", "write cpu profile to
`file`")
memprofile := flag.String("memprofile", "", "write memory profile to
`file`")
flag.Parse()
// Memory Profile
if *memprofile != "" {
f, err := os.Create(*memprofile)
if err != nil {
log.Fatal("could not create memory profile: ", err)
}
runtime.GC() // get up-to-date statistics
if err := pprof.WriteHeapProfile(f); err != nil {
log.Fatal("could not write memory profile: ", err)
}
f.Close()
}
}
consume: Started
produce: Started
produce: Sending 0
produce: Sending 1
consume: Received: 0
consume: Received: 1
produce: Sending 2
produce: Sending 3
consume: Received: 2
consume: Received: 3
produce: Sending 4
produce: Done
Illustration of Sleeping Barber Problem in Golang
The barber has one barber's chair in a cutting room and a waiting room containing a number of
chairs in it. When the barber finishes cutting a customer's hair, he dismisses the customer and
goes to the waiting room to see if there are others waiting. If there are, he brings one of them
back to the chair and cuts their hair. If there are none, he returns to the chair and sleeps in it.
Each customer, when they arrive, looks to see what the barber is doing. If the barber is sleeping,
the customer wakes him up and sits in the cutting room chair. If the barber is cutting hair, the
customer stays in the waiting room. If there is a free chair in the waiting room, the customer sits
in it and waits their turn. If there is no free chair, the customer leaves.
package main
import (
"fmt"
"sync"
"time"
)
const (
sleeping = iota
checking
cutting
)
// customer goroutine
// just fizzles out if it's full, otherwise the customer
// is passed along to the channel handling it's haircut etc
func customer(c *Customer, b *Barber, wr chan<- *Customer, wakers chan<-
*Customer) {
// arrive
time.Sleep(time.Millisecond * 50)
// Check on barber
b.Lock()
fmt.Printf("Customer %s checks %s barber | room: %d, w %d - customer:
%s\n",
c, stateLog[b.state], len(wr), len(wakers), b.customer)
switch b.state {
case sleeping:
select {
case wakers <- c:
default:
select {
case wr <- c:
default:
wg.Done()
}
}
case cutting:
select {
case wr <- c:
default: // Full waiting room, leave shop
wg.Done()
}
case checking:
panic("Customer shouldn't check for the Barber when Barber is
Checking the waiting room")
}
b.Unlock()
}
func main() {
b := NewBarber()
b.name = "Rocky"
WaitingRoom := make(chan *Customer, 5) // 5 chairs
Wakers := make(chan *Customer, 1) // Only one waker at a time
go barber(b, WaitingRoom, Wakers)
time.Sleep(time.Millisecond * 100)
wg = new(sync.WaitGroup)
n := 10
wg.Add(10)
// Spawn customers
for i := 0; i < n; i++ {
time.Sleep(time.Millisecond * 50)
c := new(Customer)
go customer(c, b, WaitingRoom, Wakers)
}
wg.Wait()
fmt.Println("No more customers for the day")
}
Checking waiting room: 0
Sleeping Barber - <nil>
Customer 120 checks Sleeping barber | room: 0, w 0 - customer: <nil>
Woken by 120
..............
..............
Checking waiting room: 0
No more customers for the day
Illustration of Cigarette Smokers Problem in Golang
Assume a cigarette requires three ingredients to make and smoke: tobacco, paper, and matches.
There are three smokers around a table, each of whom has an infinite supply of one of the three
ingredients — one smoker has an infinite supply of tobacco, another has paper, and the third has
matches. A fourth party, with an unlimited supply of everything, chooses at random a smoker,
and put on the table the supplies needed for a cigarrette. The chosen smoker smokes, and the
process should repeat indefinitely.
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
const (
paper = iota
grass
match
)
func smoker(t *Table, name string, smokes int, signal chan int) {
var chosen = -1
for {
chosen = <-signal // blocks
if smokes != chosen {
continue
}
const LIMIT = 1
var wg *sync.WaitGroup
func main() {
wg = new(sync.WaitGroup)
table := new(Table)
table.match = make(chan int, LIMIT)
table.paper = make(chan int, LIMIT)
table.grass = make(chan int, LIMIT)
var signals [3]chan int
// three smokers
for i := 0; i < 3; i++ {
signal := make(chan int, 1)
signals[i] = signal
go smoker(table, names[i], i, signal)
}
fmt.Printf("%s, %s, %s, sit with \n%s, %s, %s\n\n", names[0],
names[1], names[2], smokeMap[0], smokeMap[1], smokeMap[2])
arbitrate(table, signals)
}
Sandy, Apple, Daisy, sit with
paper, grass, match
Chapter ..
Logging Go Programs
The standard library package log provides a basic infrastructure for log management in GO
language that can be used for logging our GO programs. The main purpose of logging is to get a
trace of what's happening in the program, where it's happening, and when it's happening. Logs
can be providing code tracing, profiling, and analytics. Logging(eyes and ears of a programmer)
is a way to find those bugs and learn more about how the program is functioning.
"log"
In its simplest usage, it formats messages and sends them to Standard Error check below
example:
import (
"log"
func init(){
log.SetPrefix("LOG: ")
log.Println("init started")
func main() {
log.Println("main started")
log.Fatalln("fatal message")
log.Panicln("panic message")
After executing this code, the output would look something like this:
Sending messages to Standard Error is useful for simple tools. When we're building servers,
applications, or system services, we need a better place to send your log messages. Here all error
messages are all sent to Standard Error, regardless of whether the message is an actual error or an
informational message.
The standard log entry contains below things:
- a prefix (log.SetPrefix("LOG: "))
- a datetime stamp (log.Ldate)
- full path to the source code file writing to the log (log.Llongfile)
- the line of code performing the write and finally the message.
This pieces of information are automatically generated for us, information about when the event
happened and information about where it happened.
Now i am taking a real world example and implementing above log package in my program. For
example i am testing an SMTP connection is working fine or not. For test case I am going to
connect to a SMTP server "smtp.smail.com" which is not exist, hence program will terminate
with a log message.
package main
import (
"log"
"net/smtp"
func init(){
log.SetPrefix("TRACE: ")
log.Println("init started")
func main() {
if err != nil {
log.Fatalln(err)
client.Data()
Chapter ………..
import (
"log"
"os"
)
func main() {
emptyFile, err := os.Create("empty.txt")
if err != nil {
log.Fatal(err)
}
log.Println(emptyFile)
emptyFile.Close()
}
C:\golang\working-with-files>go fmt example1.go C:\golang\working-with-files>golint
example1.go C:\golang\working-with-files>go run example1.go 2018/08/11 15:46:04
&{0xc042060780} C:\golang\working-with-files>
import (
"log"
"os"
)
func main() {
_, err := os.Stat("test")
if os.IsNotExist(err) {
errDir := os.MkdirAll("test", 0755)
if errDir != nil {
log.Fatal(err)
}
}
}
import (
"log"
"os"
)
func main() {
oldName := "test.txt"
newName := "testing.txt"
err := os.Rename(oldName, newName)
if err != nil {
log.Fatal(err)
}
}
os.Rename() can also move file from one location to another at same time renaming file name.
package main
import (
"log"
"os"
)
func main() {
oldLocation := "/var/www/html/test.txt"
newLocation := "/var/www/html/src/test.txt"
err := os.Rename(oldLocation, newLocation)
if err != nil {
log.Fatal(err)
}
}
import (
"io"
"log"
"os"
)
func main() {
[root@server src]# clear [root@server src]# go run example6.go 2018/08/15 03:43:39 Copied
100 bytes. [root@server src]#
Get file information in Golang
package main
import (
"fmt"
"log"
"os"
)
func main() {
fileStat, err := os.Stat("test.txt")
if err != nil {
log.Fatal(err)
}
import (
"log"
"os"
)
func main() {
err := os.Remove("/var/www/html/test.txt")
if err != nil {
log.Fatal(err)
}
}
func main() {
filename := "test.txt"
for data.Scan() {
fmt.Print(data.Text())
}
}
os.Truncate() function will reduce the file content upto N bytes passed in second parameter. In
below example if size of test.txt file is more that 1Kb(100 byte) then it will truncate the
remaining content.
package main
import (
"log"
"os"
)
func main() {
err := os.Truncate("test.txt", 100)
if err != nil {
log.Fatal(err)
}
}
import (
"fmt"
"os"
)
func main() {
message := "Add this content at end"
filename := "test.txt"
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
defer f.Close()
import (
"log"
"os"
"time"
)
func main() {
// Test File existence.
_, err := os.Stat("test.txt")
if err != nil {
if os.IsNotExist(err) {
log.Fatal("File does not exist.")
}
}
log.Println("File exist.")
import (
"archive/zip"
"fmt"
"io"
"log"
"os"
)
return nil
}
func main() {
flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC
file, err := os.OpenFile("test.zip", flags, 0644)
if err != nil {
log.Fatalf("Failed to open zip for writing: %s", err)
}
defer file.Close()
zipw := zip.NewWriter(file)
defer zipw.Close()
for _, filename := range files {
if err := appendFiles(filename, zipw); err != nil {
log.Fatalf("Failed to add file %s to zip: %s",
filename, err)
}
}
}
import (
"archive/zip"
"fmt"
"log"
"os"
)
if err != nil {
msg := "Failed to read zip %s for reading: %s"
return fmt.Errorf(msg, file.Name, err)
}
fmt.Println()
return nil
}
func main() {
read, err := zip.OpenReader("test.zip")
if err != nil {
msg := "Failed to open: %s"
log.Fatalf(msg, err)
}
defer read.Close()
import (
"archive/zip"
"io"
"log"
"os"
"path/filepath"
)
func main() {
zipReader, _ := zip.OpenReader("test.zip")
for _, file := range zipReader.Reader.File {
targetDir := "./"
extractedFilePath := filepath.Join(
targetDir,
file.Name,
)
if file.FileInfo().IsDir() {
log.Println("Directory Created:", extractedFilePath)
os.MkdirAll(extractedFilePath, file.Mode())
} else {
log.Println("File extracted:", file.Name)
Chapter …
Explain the term Cryptography in brief
The term "cryptography" is evolved from two Greek words, namely crypto and graphy. As per
Greek language, crypto means secret and graphy means writing. The term crypto has become
more popular with the introduction of all crypto currencies like Bitcoin, Ethereum, and Litecoin.
What is Cryptography?
In simple terms, the process of altering messages in a way that their meaning is hidden from an
enemy or opponent who might seize them, is known as Cryptography. Cryptography is the
science of secret writing that brings numerous techniques to safeguard information that is present
in an unreadable format. Only the designated recipients can be converted this unreadable format
into the readable format.
Components of Cryptography
Plaintext: Plaintext can be text, binary code, or an image that needs to be converted into a
format that is unreadable by anybody except those who carry the secret to unlocking it. It refers
to the original unencrypted or unadulterated message that the sender wishes to send.
Ciphertext: During the process of encryption plaintext get converted into a rushed format, the
resulting format is called the ciphertext. It relates to the encrypted message, the receiver receives
that. However, ciphertext is like the plaintext that has been operated on by the encryption process
to reproduce a final output. This final output contains the original message though in a format,
that is not retrievable unless official knows the correct means or can crack the code.
Encryption: Encryption, receives information and transforms it to an unreadable format that can
be reversed. It is the process of encrypting the plaintext so it can provide the ciphertext.
Encryption needs an algorithm called a cipher and a secret key. No one can decrypt the vital
information on the encrypted message without knowing the secret key. Plaintext gets
transformed into ciphertext using the encryption cipher.
Decryption: This is the reverse of the encryption process, in which it transforms the ciphertext
back into the plaintext using a decryption algorithm and a secret key. In symmetric encryption,
the key used to decrypt is the same as the key used to encrypt. On other hand, in asymmetric
encryption or public-key encryption the key used to decrypt differs from the key used to encrypt.
Ciphers: The encryption and decryption algorithms are together known as ciphers. Perhaps the
trickiest, interesting and most curious part in the encryption process is the algorithm or cipher.
The algorithm or cipher is nothing more than a formula that comprises various steps that
illustrate how the encryption/decryption process is being implemented on an information. A basic
cipher takes bits and returns bits and it doesn't care whether bits represents textual information,
an image, or a video.
Key: A key is generally a number or a set of numbers on which the cipher operates. In technical
terms, a key is a discrete piece of information that is used to control the output (ciphertext and
plaintext) of a given cryptographic algorithm. Encryption and decryption algorithms needs this
key to encrypt or decrypt messages, respectively. Sender uses the encryption algorithm and the
secret key to convert the plaintext into the ciphertext. On other hand receiver uses same
decryption algorithm and the secret key to convert ciphertext back into the plaintext. The longer
the secret key is, the harder it is for an attacker to decrypt the message.
Below is very basic example, we have created a simple cipher to encrypt and decrypt a plaintext
into ciphertext and vice versa. The algorithm cipherAlgorithm() is same for encryption and
decryption. The key, we have used is 01, 10 and 15 to encrypt and decrypt the message. The
output of encryption is different each time when the key is different. This cipher shifts the letter
based on key value, key plays an important role in cryptography.
package main
import (
"fmt"
"unicode"
)
func main() {
c := NewCaesar(1)
fmt.Println("Encrypt Key(01) abcd =>", c.Encryption("abcd"))
fmt.Println("Decrypt Key(01) bcde =>", c.Decryption("bcde"))
fmt.Println()
c = NewCaesar(10)
fmt.Println("Encrypt Key(10) abcd =>", c.Encryption("abcd"))
fmt.Println("Decrypt Key(10) klmn =>", c.Decryption("klmn"))
fmt.Println()
c = NewCaesar(15)
fmt.Println("Encrypt Key(15) abcd =>", c.Encryption("abcd"))
fmt.Println("Decrypt Key(15) pqrs =>", c.Decryption("pqrs"))
}
Output of above
C:\golang\example>go run test8.go
Encrypt Key(01) abcd => bcde
Decrypt Key(01) bcde => abcd
C:\golang\example>
Go provides extensive options for cryptography, such as encryption, hashing. Go have packages
to support symmetric encryption algorithms: base64, AES and DES, this we will cover in
coming tutorials.
Chapter …….
package main
import (
"fmt"
"regexp"
"strings"
)
func main() {
str1 := "this is a [sample] [[string]] with [SOME] special words"
re := regexp.MustCompile(`\[([^\[\]]*)\]`)
fmt.Printf("Pattern: %v\n", re.String()) // print pattern
fmt.Println("Matched:", re.MatchString(str1)) // true
package main
import (
"fmt"
"regexp"
)
func main() {
str1 := "We @@@Love@@@@ #Go!$! ****Programming****Language^^^"
re := regexp.MustCompile(`[^a-zA-Z0-9]+`)
package main
import (
"fmt"
"regexp"
)
func main() {
str1 := "If I am 20 years 10 months and 14 days old as of August
17,2016 then my DOB would be 1995-10-03"
re := regexp.MustCompile(`\d{4}-\d{2}-\d{2}`)
fmt.Println(re.MatchString(str1)) // true
package main
import (
"fmt"
"regexp"
)
func main() {
str1 := `Proxy Port Last Check Proxy Speed Proxy Country Anonymity
118.99.81.204
118.99.81.204 8080 34 sec Indonesia - Tangerang Transparent 2.184.31.2
8080 58 sec
Iran Transparent 93.126.11.189 8080 1 min Iran - Esfahan Transparent
202.118.236.130
7777 1 min China - Harbin Transparent 62.201.207.9 8080 1 min Iraq
Transparent`
re := regexp.MustCompile(`(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}`)
package main
import (
"fmt"
"regexp"
)
func main() {
str1 := `http://www.suon.co.uk/product/1/7/3/`
re := regexp.MustCompile(`^(?:https?:\/\/)?(?:[^@\/\n]+@)?(?:www\.)?
([^:\/\n]+)`)
fmt.Printf("Pattern: %v\n", re.String()) // print pattern
fmt.Println(re.MatchString(str1)) // true
submatchall := re.FindAllString(str1,-1)
for _, element := range submatchall {
fmt.Println(element)
}
}
Pattern: ^(?:https?:\/\/)?(?:[^@\/\n]+@)?(?:www\.)?([^:\/\n]+)
true
http://www.suon.co.uk
package main
import (
"fmt"
"regexp"
)
func main() {
str1 := "ç$€§/az@gmail.com"
str2 := "abcd@gmail_yahoo.com"
str3 := "abcd@gmail-yahoo.com"
str4 := "abcd@gmailyahoo"
str5 := "abcd@gmail.yahoo"
re := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-
9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-
zA-Z0-9])?)*$")
package main
import (
"fmt"
"regexp"
)
func main() {
str1 := "1(234)5678901x1234"
str2 := "(+351) 282 43 50 50"
str3 := "90191919908"
str4 := "555-8909"
str5 := "001 6867684"
str6 := "001 6867684x1"
str7 := "1 (234) 567-8901"
str8 := "1-234-567-8901 ext1234"
re := regexp.MustCompile(`^(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d?)\)?)?
[\-\.\ \\\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\\/]?){0,})(?:[\-\.\ \\\/]?(?:#|ext\.?|
extension|x)[\-\.\ \\\/]?(\d+))?$`)
package main
import (
"fmt"
"regexp"
)
func main() {
str1 := "31/07/2010"
str2 := "1/13/2010"
str3 := "29/2/2007"
str4 := "31/08/2010"
str5 := "29/02/200a"
str6 := "29/02/200a"
str7 := "55/02/200a"
str8 := "2_/02/2009"
re := regexp.MustCompile("(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/
((19|20)\\d\\d)")
fmt.Printf("Pattern: %v\n", re.String()) // print pattern
fmt.Printf("\nDate: %v :%v\n", str1, re.MatchString(str1))
fmt.Printf("Date: %v :%v\n", str2, re.MatchString(str2))
fmt.Printf("Date: %v :%v\n", str3, re.MatchString(str3))
fmt.Printf("Date: %v :%v\n", str4, re.MatchString(str4))
fmt.Printf("Date: %v :%v\n", str5, re.MatchString(str5))
fmt.Printf("Date: %v :%v\n", str6, re.MatchString(str6))
fmt.Printf("Date: %v :%v\n", str7, re.MatchString(str7))
fmt.Printf("Date: %v :%v\n", str8, re.MatchString(str8))
}
Pattern: (0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/((19|20)\d\d)
Date: 31/07/2010 :true
Date: 1/13/2010 :false
Date: 29/2/2007 :true
Date: 31/08/2010 :true
Date: 29/02/200a :false
Date: 29/02/200a :false
Date: 55/02/200a :false
Date: 2_/02/2009 :false
package main
import (
"fmt"
"regexp"
)
func main() {
str1 := "4111111111111111"
str2 := "346823285239073"
str3 := "370750517718351"
str4 := "4556229836495866"
str5 := "5019717010103742"
str6 := "76009244561"
str7 := "4111-1111-1111-1111"
str8 := "5610591081018250"
str9 := "30569309025904"
str10 := "6011111111111117"
re := regexp.MustCompile(`^(?:4[0-9]{12}(?:[0-9]{3})?|[25][1-7][0-9]
{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]
{11}|(?:2131|1800|35\d{3})\d{11})$`)
import (
"fmt"
"log"
"regexp"
)
func main() {
reg, err := regexp.Compile("[^A-Za-z0-9]+")
if err != nil {
log.Fatal(err)
}
newStr := reg.ReplaceAllString("#Golang#Python$Php&Kotlin@@", "-")
fmt.Println(newStr)
}
-Golang-Python-Php-Kotlin-
import (
"fmt"
"regexp"
)
func main() {
strEx := "Php-Golang-Php-Python-Php-Kotlin"
reStr := regexp.MustCompile("^(.*?)Php(.*)$")
repStr := "${1}Java$2"
output := reStr.ReplaceAllString(strEx, repStr)
fmt.Println(output)
}
Java-Golang-Php-Python-Php-Kotlin
import (
"fmt"
"regexp"
)
func main() {
str1 := "Split String on \nwhite \tspaces."
re := regexp.MustCompile(`\S+`)
import (
"fmt"
"regexp"
)
func main() {
str1 := "Hello X42 I'm a Y-32.35 string Z30"
re := regexp.MustCompile(`[-]?\d[\d,]*[\.]?[\d{2}]*`)
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile(`^(.*/)?(?:$|(.+?)(?:(\.[^.]*$)|$))`)
str1 := `http://www.golangprograms.com/regular-expressions.html`
match1 := re.FindStringSubmatch(str1)
fmt.Println(match1[2])
str2 := `/home/me/dir3/dir3a/dir3ac/filepat.png`
match2 := re.FindStringSubmatch(str2)
fmt.Println(match2[2])
}
regular-expressions
filepat
import (
"fmt"
"regexp"
)
func main() {
str1 := "Hello X42 I'm a Y-32.35 string Z30"
re := regexp.MustCompile(`[A-Z][^A-Z]*`)
import (
"fmt"
"regexp"
"strings"
)
func main() {
str1 := "This is a (sample) ((string)) with (SOME) special words"
re := regexp.MustCompile(`\((.*?)\)`)
fmt.Printf("Pattern: %v\n", re.String()) // print pattern
import (
"fmt"
"log"
"regexp"
)
func main() {
str1 := "how much for the maple syrup? $20.99? That's ridiculous!!!"
import (
"fmt"
"regexp"
)
func main() {
str1 := `<img src="1.png"><x><z?>
<img czx zcxz src='2.png'><x><z?>`
re := regexp.MustCompile(`<img[^>]+\bsrc=["']([^"']+)["']`)
import (
"fmt"
"regexp"
)
func main() {
var emojiRx = regexp.MustCompile(`[\x{1F600}-\x{1F6FF}|
[\x{2600}-\x{26FF}]`)
var str = emojiRx.ReplaceAllString("Thats a nice joke 😆😆😆
😛", `[e]`)
fmt.Println(str)
}
Thats a nice joke [e][e][e] [e]
How to extract text from between html tag using Regular Expressions in
Golang?
package main
import (
"fmt"
"regexp"
)
func main() {
str1 := `<html><body>
<form name="query"
action="http://www.example.net/action.php" method="post">
<textarea type="text" name="nameiknow">The text
I want</textarea>
<div id="button">
<input type="submit" value="Submit" />
</div>
</form>
</body></html>`
re := regexp.MustCompile(`<textarea.*?>(.*)</textarea>`)
import (
"fmt"
"regexp"
)
func main() {
str1 := "8:2"
str2 := "9:9"
str3 := "12:29"
str4 := "02:5"
str5 := "23:59"
str6 := "55:59"
str7 := "0:01"
re := regexp.MustCompile(`^([0-9]|0[0-9]|1[0-9]|2[0-3]):([0-9]|[0-5]
[0-9])$`)
Chapter ….
In this example, we are going to create an interface as database front end to handle these operations.
We have Employee table containing Employee information like id, name and city. With this table, we
have to perform CRUD using MySQL.
Using Git Bash first install driver for Go's MySQL database package. Run below command and
install MySQL driver's
go get -u github.com/go-sql-driver/mysql
1. Open PHPMyAdmin/SQLyog or what ever MySQL database management tool that you are
using.
2. Create a new database "goblog"
Execute the following SQL query to create a table named Employee inside your MySQL
database. We will use this table for all of our future operations.
Let's create a file named main.go and put the following code inside it.
We usually import database/sql and use sql to execute database queries on the database.
Function dbConn opens connection with MySQL driver.
We will create Employee struct that has following properties: Id, Name and City.
package main
import (
"database/sql"
"log"
"net/http"
"text/template"
_ "github.com/go-sql-driver/mysql"
)
func main() {
log.Println("Server started on: http://localhost:8080")
http.HandleFunc("/", Index)
http.HandleFunc("/show", Show)
http.HandleFunc("/new", New)
http.HandleFunc("/edit", Edit)
http.HandleFunc("/insert", Insert)
http.HandleFunc("/update", Update)
http.HandleFunc("/delete", Delete)
http.ListenAndServe(":8080", nil)
}
Now it's time to build the Template files of our CRUD application. Create form folder at same
location where we have created main.go.
a) Let's create a file named Index.tmpl inside the form folder and put the following code inside
it.
{{ define "Index" }}
{{ template "Header" }}
{{ template "Menu" }}
<h2> Registered </h2>
<table border="1">
<thead>
<tr>
<td>ID</td>
<td>Name</td>
<td>City</td>
<td>View</td>
<td>Edit</td>
<td>Delete</td>
</tr>
</thead>
<tbody>
{{ range . }}
<tr>
<td>{{ .Id }}</td>
<td> {{ .Name }} </td>
<td>{{ .City }} </td>
<td><a href="/show?id={{ .Id }}">View</a></td>
<td><a href="/edit?id={{ .Id }}">Edit</a></td>
<td><a href="/delete?id={{ .Id }}">Delete</a><td>
</tr>
{{ end }}
</tbody>
</table>
{{ template "Footer" }}
{{ end }}
b) Now create another file named Header.tmpl inside the same form folder and put the
following code inside it.
{{ define "Header" }}
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Golang Mysql Curd Example</title>
<meta charset="UTF-8" />
</head>
<body>
<h1>Golang Mysql Curd Example</h1>
{{ end }}
c) Now create another file named Footer.tmpl inside the same form folder and put the
following code inside it.
{{ define "Footer" }}
</body>
</html>
{{ end }}
d) Now create another file named Menu.tmpl inside the same form folder and put the following
code inside it.
{{ define "Menu" }}
<a href="/">HOME</a> |
<a href="/new">NEW</a>
{{ end }}
e) Next, we have to create Show.tmpl file for item details page, so again create this file in form
folder.
{{ define "Show" }}
{{ template "Header" }}
{{ template "Menu" }}
<h2> Register {{ .Id }} </h2>
<p>Name: {{ .Name }}</p>
<p>City: {{ .City }}</p><br /> <a href="/edit?id={{
.Id }}">Edit</a></p>
{{ template "Footer" }}
{{ end }}
f) Now we create new blade file for create new item, it's call New.tmpl file inside form.
{{ define "New" }}
{{ template "Header" }}
{{ template "Menu" }}
<h2>New Name and City</h2>
<form method="POST" action="insert">
<label> Name </label><input type="text" name="name" /><br />
<label> City </label><input type="text" name="city" /><br />
<input type="submit" value="Save user" />
</form>
{{ template "Footer" }}
{{ end }}
g) At last, we need to create Edit.tmpl file for update item, so again create this file in form
folder.
{{ define "Edit" }}
{{ template "Header" }}
{{ template "Menu" }}
<h2>Edit Name and City</h2>
<form method="POST" action="update">
<input type="hidden" name="uid" value="{{ .Id }}" />
<label> Name </label><input type="text" name="name" value="{{ .Name }}"
/><br />
<label> City </label><input type="text" name="city" value="{{ .City }}"
/><br />
<input type="submit" value="Save user" />
</form><br />
{{ template "Footer" }}
{{ end }}
After a long journey finally we've created all files of our CRUD application with Golang and MySQL.
Run the following command
go run main.go
http://localhost:8080/
Chapter …
An interface type is defined with the keyword interface. An interface defines a set of methods
(the method set), but these methods do not contain code: they are not implemented (they are
abstract). A method set is a list of methods that a type must have in order to implement the
interface. Also an interface cannot contain variables.
shipping() float64
tax() float64
The interface type catalog is a contract for creating various product types in a catalog. The
catalog interface provides two behaviors in its contract: shipping and tax.
Implementing an interface
The following source code shows the configurable type as an implementation of the interface
type catalog. The configurable type is defined as a struct with receiver methods shipping and tax.
This fact automatically qualifies configurable as an implementation of catalog:
package main
import "fmt"
shipping() float64
tax() float64
name string
return c.qty * 5
func main() {
tshirt := configurable{}
tshirt.price = 250
tshirt.qty = 2
When you run the program, you get the following output:
C:\golang>go run example.go
Shipping Charge: 10
Tax: 25
Go support composition (has-a) relationships when building objects using subtyping via
interfaces. This can be explained that the configurable, download, simple type (and any other
type that implements the methods shipping and tax) can be treated as a subtype of catalog, as
shown in the following figure:
package main
import "fmt"
shipping() float64
tax() float64
name string
return c.qty * 5
name string
name string
return s.qty * 3
func main() {
tshirt := configurable{}
tshirt.price = 250
tshirt.qty = 2
fmt.Println("Configurable Product")
fmt.Println("\nSimple Product")
fmt.Println("\nDownloadable Product")
When you run the program, you get the following output:
C:\golang>go run example.go
Configurable Product
Shipping Charge: 10
Tax: 25
Simple Product
Shipping Charge: 75
Tax: 7.5
Downloadable Product
Tax: 1.33
C:\golang>
Multiple interfaces
In GO, the implicit mechanism of interfaces allows to satisfy multiple interface type at once.
This can be implemented by intergrating the method set of a given type intersect with the
methods of each interface type. Let us re-implement the previous code. New interface discount
has been created. This is illustrated by the following figure:
package main
import "fmt"
shipping() float64
tax() float64
}
type discount interface{
offer() float64
name string
return c.qty * 5
name string
}
func (d *download) tax() float64{
name string
return s.qty * 3
func main() {
tshirt := configurable{}
tshirt.price = 250
tshirt.qty = 2
fmt.Println("Configurable Product")
fmt.Println("\nSimple Product")
fmt.Println(mobile.name)
fmt.Println("\nDownloadable Product")
fmt.Println(book.name)
When you run the program, you get the following output:
C:\golang>go run example.go
Configurable Product
Shipping Charge: 10
Tax: 25
Discount: 37.5
Simple Product
Samsung S-7
Shipping Charge: 6
Tax: 180
Discount: 300
Downloadable Product
Python in 24 Hours
Tax: 5
C:\golang>
Interface embedding
In GO, the interface type also support for type embedding (similar to the struct type). This gives
you the flexibility to structure your types in ways that maximize type reuse.
Continuing with the catalog example, a struct configurable is declared in which the type discount
and giftpack is embedded. Here you create more concrete types of the catalog interface. Because
type giftpack and discount is an implementation of the catalog interface, the type configurable is
also an implementation of the catalog interface. All fields and methods defined in the Type
discount and giftpack types are also available in the configurable type.
The following illustration shows how the interface types may be combined so the is-a
relationship still satisfies the relationships between code components:
package main
import "fmt"
offer() float64
available() string
discount
giftpack
shipping() float64
tax() float64
name string
}
func (c *configurable) shipping() float64{
return c.qty * 5
name string
name string
return s.qty * 3
func main() {
tshirt := configurable{}
tshirt.price = 1550
tshirt.qty = 2
fmt.Println("Configurable Product")
fmt.Println(tshirt.available())
fmt.Println("\nSimple Product")
fmt.Println(mobile.name)
fmt.Println("\nDownloadable Product")
fmt.Println(book.name)
fmt.Println(book.available())
When you run the program, you get the following output:
C:\golang>go run example.go
Configurable Product
Shipping Charge: 10
Tax: 155
Discount: 232.5
Gift Pack Available
Simple Product
Samsung S-7
Shipping Charge: 6
Tax: 180
Discount: 300
Downloadable Product
Python in 24 Hours
Tax: 5
Gift Pack not Available
C:\golang>