├── .gitignore
├── Basics
├── 0 - about-golang
│ └── README.md
├── 1 - installation
│ └── README.md
├── 10 - switch
│ └── switch.go
├── 11 - arrays
│ └── arrays.go
├── 12 - slices
│ └── slices.go
├── 13 - maps
│ └── maps.go
├── 14 - range
│ └── range.go
├── 15 - functions
│ └── function.go
├── 16 - struct
│ └── struct.go
├── 17 - methods
│ └── methods.go
├── 18 - pointers
│ └── pointers.go
├── 19 - interface
│ └── interface.go
├── 2 - hello-world
│ ├── README.md
│ └── main.go
├── 20 - empty-interface
│ └── empty_interface.go
├── 21 - goroutines
│ ├── GoRoutines.pptx
│ └── goroutines.go
├── 22 - blank-identifier
│ └── blank_identifies.go
├── 23 - defer
│ └── defer.go
├── 24 - panic
│ └── panic.go
├── 25 - recover
│ └── recover.go
├── 26 - select
│ └── select.go
├── 27 - nil
│ └── nil.go
├── 28 - packages
│ ├── controller
│ │ └── controller.go
│ ├── go.mod
│ └── main.go
├── 3 - go-cli
│ └── README.md
├── 4 - basic-questions
│ ├── README.md
│ └── main.go
├── 5 - values
│ └── values.go
├── 6 - variables
│ └── variables.go
├── 7 - constant
│ └── constant.go
├── 8 - for
│ └── for.go
├── 9 - if-else
│ └── if_else.go
└── README.md
├── README.md
├── advanced
├── bitwise-operators
│ └── main.go
├── char
│ └── main.go
├── concurrency
│ ├── dining_philosophers
│ │ └── dining_philosophers.go
│ ├── go.mod
│ ├── go.sum
│ ├── producer_consumer
│ │ └── producer_consumer.go
│ └── sleeping_barber
│ │ └── sleeping_barber.go
├── context
│ └── context.go
├── deadlock
│ └── deadlock.go
├── iota
│ └── main.go
├── keywords
│ ├── fallthrough.go
│ └── goto.go
├── livelock
│ └── livelock.go
├── new_vs_make
│ └── main.go
├── strings
│ └── strings.go
└── sync_pkg
│ ├── mutex.go
│ └── waitGroup.go
├── resource
├── e-books
│ └── README.md
└── web-sites
│ └── README.md
├── testing
├── go.mod
├── main.go
└── main_test.go
└── web-server
├── 1 - hello-world
└── main.go
├── 2 - routing
└── main.go
├── 3 - middleware
└── main.go
├── 4 - static-directory
├── main.go
└── static
│ └── index.html
├── 5 - templates
├── main.go
└── templates
│ └── home.gohtml
├── 6 - tls-protocol
├── request.http
└── server.go
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | .env
4 | .idea
5 | server.key
6 | server.crt
--------------------------------------------------------------------------------
/Basics/0 - about-golang/README.md:
--------------------------------------------------------------------------------
1 | ## The GO programming language
2 |
3 | Go is a statically typed, compiled programming language designed at Google by Robert Griesemer, Rob Pike, and Ken Thompson. Go is syntactically similar to C, but with memory safety, garbage collection, structural typing, and CSP-style concurrency.
4 |
5 | ## زبان برنامه نویسی گو
6 |
7 | «زبان برنامهنویسی گو» (Go Programming Language) که با عنوان «گولَنگ» (Golang) نیز شناخته شده، زبان برنامهنویسی کامپیوتری توسعه یافته توسط گوگل است. توسعه این زبان برنامهنویسی در سال ۲۰۰۷ در گوگل آغاز شد. گو (Go) در سال ۲۰۰۹ به صورت عمومی معرفی شد. سه توسعهدهنده اصلی زبان Go در گوگل، «رابرت گریسیمر» (Robert Griesemer)، «راب پایک» (Rob Pike) و «کن تامپسون» (Ken Thompson) هستند. آنها در تلاش بودند تا زبانی را بسازند که نحو آن به طور ضعیف مبتنی بر زبان برنامهنویسی C باشد. در واقع، زبان گو از نظر «نحوی» (Syntactically) شبیه به C است، ولی دارای قابلیتهای دیگری مانند «ایمنی حافظه» (Memory Safety)، «بازیافت حافظه» (Garbage Collection)، «سیستم نوع ساختاری» (Structural Typing) و «همروندی استایل ارتباط فرایندهای متوالی» (CSP-Style Concurrency) است.
8 |
--------------------------------------------------------------------------------
/Basics/1 - installation/README.md:
--------------------------------------------------------------------------------
1 | ## Download GO
2 |
3 | Click to this link (https://golang.org/doc/install) and download GO for your operation
4 | system.
5 |
6 | ## Install GO
7 |
8 | # for windows
9 |
10 | 1- Open the MSI file you downloaded and follow the prompts to install Go.
11 | By default, the installer will install Go to Program Files or Program Files (x86). You can change the location as needed. After installing, you will need to close and reopen any open command prompts so that changes to the environment made by the installer are reflected at the command prompt.
12 |
13 | 2- Verify that you've installed Go.
14 | In Windows, click the Start menu.
15 | In the menu's search box, type cmd, then press the Enter key.
16 | In the Command Prompt window that appears, type the following command:
17 |
18 | ```
19 | $ go version
20 | ```
21 |
22 | 3- Confirm that the command prints the installed version of Go.
23 |
24 | # for mac
25 |
26 | 1- Open the package file you downloaded and follow the prompts to install Go.
27 | The package installs the Go distribution to /usr/local/go. The package should put the /usr/local/go/bin directory in your PATH environment variable. You may need to restart any open Terminal sessions for the change to take effect.
28 |
29 | 2- Verify that you've installed Go by opening a command prompt and typing the following command:
30 |
31 | ```
32 | $ go version
33 | ```
34 |
35 | 3- Confirm that the command prints the installed version of Go.
36 |
37 | # for linux
38 |
39 | 1- Extract the archive you downloaded into /usr/local, creating a Go tree in /usr/local/go.
40 | Important: This step will remove a previous installation at /usr/local/go, if any, prior to extracting. Please back up any data before proceeding.
41 |
42 | For example, run the following as root or through sudo:
43 |
44 | ```
45 | rm -rf /usr/local/go && tar -C /usr/local -xzf go1.17.linux-amd64.tar.gz
46 | ```
47 |
48 | 2- Add /usr/local/go/bin to the PATH environment variable.
49 | You can do this by adding the following line to your $HOME/.profile or /etc/profile (for a system-wide installation):
50 |
51 | ```
52 | export PATH=$PATH:/usr/local/go/bin
53 | ```
54 |
55 | Note: Changes made to a profile file may not apply until the next time you log into your computer. To apply the changes immediately, just run the shell commands directly or execute them from the profile using a command such as source $HOME/.profile.
56 |
57 | 3- Verify that you've installed Go by opening a command prompt and typing the following command:
58 |
59 | ```
60 | $ go version
61 | ```
62 |
63 | 4- Confirm that the command prints the installed version of Go.
64 |
65 | ## Complete
66 |
67 | You're set up! lets write code
68 |
--------------------------------------------------------------------------------
/Basics/10 - switch/switch.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | // Switch statements express conditionals across
7 | // many branches.
8 |
9 | x := 2
10 |
11 | switch x {
12 | case 0:
13 | fmt.Println("x variable === 0")
14 |
15 | case 1:
16 | fmt.Println("x variable === 1")
17 |
18 | case 2:
19 | fmt.Println("x variable === 2")
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/Basics/11 - arrays/arrays.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | // In Go, an array is a numbered sequence of
7 | // elements of a specific length.
8 |
9 | var a [3]int
10 | fmt.Println(a)
11 | // Here we create an array a that will hold
12 | // exactly 3 ints. The type of elements and
13 | // length are both part of the array’s type.
14 | // By default an array is zero-valued, which
15 | // for ints means 0s.
16 |
17 | a[0] = 154
18 | fmt.Println(a)
19 | // We can set a value at an index using the
20 | // array[index] = value syntax,
21 | // and get a value with array[index].
22 | fmt.Println(a[0])
23 |
24 | // The builtin len returns the length of an array
25 | fmt.Println(len(a))
26 |
27 | // second way for declaring arrays
28 | b := [3]int{}
29 | fmt.Println(b)
30 |
31 | // or
32 | c := [3]int{10, 20, 30}
33 | fmt.Println(c)
34 |
35 | // or
36 | d := [2][2]string{}
37 | d[0][0] = "erfan"
38 | d[0][1] = "john"
39 | // d[0][2] = "john" return the error becuase index
40 | // 2 in not declare
41 | fmt.Println(d)
42 | }
43 |
--------------------------------------------------------------------------------
/Basics/12 - slices/slices.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | // Slices are a key data type in Go, giving
7 | // a more powerful interface to sequences than
8 | // arrays.
9 |
10 | // Declaring
11 | slice := []int{}
12 | fmt.Println(slice)
13 |
14 | // Unlike arrays, slices are typed only by the
15 | // elements they contain (not the number of elements)
16 |
17 | // append a value
18 | slice = append(slice, 10)
19 | fmt.Println(slice)
20 | // slice[1] = 20 return the error becuase we not
21 | // define a start length
22 |
23 | sliceTwo := make([]string, 2)
24 | sliceTwo[0] = "erfan"
25 | sliceTwo[1] = "john"
26 | // sliceTwo[2] = "nothing" return the error becuase
27 | // we defined a 2 length and we can just append to
28 | // the slice
29 | sliceTwo = append(sliceTwo, "dom")
30 | fmt.Println(sliceTwo)
31 |
32 | // basic example
33 | x := []int{}
34 |
35 | for i := 0; i < 5; i++ {
36 | x = append(x, i)
37 | }
38 |
39 | fmt.Println(x)
40 | }
41 |
--------------------------------------------------------------------------------
/Basics/13 - maps/maps.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | // Maps are Go’s built-in associative data
7 | // type (sometimes called hashes or dicts in
8 | // other languages).
9 |
10 | // To create an empty map, use the builtin make:
11 | // make(map[key-type]val-type).
12 | m := make(map[int]string)
13 | m[1] = "erfan"
14 | m[2] = "john"
15 | fmt.Println(m)
16 |
17 | // The builtin delete removes key/value pairs from a map.
18 | delete(m, 1)
19 | fmt.Println(m)
20 |
21 | // The optional second return value when getting
22 | // a value from a map indicates if the key was
23 | // present in the map. This can be used to
24 | // disambiguate between missing keys and keys
25 | // with zero values like 0 or "".
26 | _, value := m[4]
27 | if !value {
28 | fmt.Println("not found!")
29 | } else {
30 | fmt.Println("true")
31 | }
32 |
33 | // You can also declare and initialize a new map in
34 | // the same line with this syntax.
35 | second := map[int]string{1: "erfan"}
36 | fmt.Println(second)
37 | }
38 |
--------------------------------------------------------------------------------
/Basics/14 - range/range.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | // range iterates over elements in a variety
7 | // of data structures
8 |
9 | nums := [4]int{1, 2, 3, 4}
10 | sum := 0
11 | for _, i := range nums {
12 | sum += i
13 | }
14 | fmt.Println(sum)
15 | // range on arrays and slices provides both
16 | // the index and value for each entry.
17 | // Above we didn’t need the index, so we ignored
18 | // it with the blank identifier _.
19 |
20 | // range on map iterates over key/value pairs.
21 | m := map[int]string{1: "erfan", 2: "john"}
22 | for key, value := range m {
23 | fmt.Println(key, value)
24 | }
25 |
26 | // range on strings iterates over Unicode code points.
27 | str := "erfan"
28 | for index, uni := range str {
29 | fmt.Println(index, uni)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Basics/15 - functions/function.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | fmt.Println(sum(1, 2))
7 | // return 3
8 |
9 | users := users("erfan", "john")
10 | fmt.Println(users)
11 | // return ["erfan" , "john"]
12 |
13 | // Closure functions
14 | // GO functions can contain functions
15 | hello := func(name string) {
16 | fmt.Println("hello", name)
17 | }
18 | hello("erfan")
19 | // return hello erfan
20 |
21 | name, age := multipleReturns("erfan", 17)
22 | fmt.Println(name, age)
23 | // return erfan , 17
24 |
25 | fake := fakeFunc(1)
26 | fmt.Println(fake)
27 | // return 2
28 | }
29 |
30 | // Here’s a function that takes two ints and
31 | // returns their sum as an int.
32 | func sum(a, b int) int {
33 | return a + b
34 | }
35 |
36 | // or
37 | // func sum(a int , b int) int {}
38 |
39 | // Variadic functions can be called with any number of
40 | // trailing arguments for example:
41 | func users(names ...string) []string {
42 | return names
43 | }
44 |
45 | // Multiple Return Values
46 | func multipleReturns(name string, age int) (string, int) {
47 | return name, age
48 | }
49 |
50 | // Recursive functions
51 | func fakeFunc(x int) int {
52 | if x == 0 {
53 | return 1
54 | }
55 |
56 | return x + fakeFunc(x-1)
57 | }
58 |
--------------------------------------------------------------------------------
/Basics/16 - struct/struct.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // Data structure. collection of properties that are
6 | // related together
7 | // This car struct type has name, model,
8 | // engine and price fields
9 | type car struct {
10 | name string
11 | model string
12 | engine string
13 | price string
14 | }
15 |
16 | func main() {
17 | // New car
18 | var myCar car
19 |
20 | // Set values
21 | myCar.engine = "hemi 6.2L supercharged"
22 | myCar.model = "dodge"
23 | myCar.name = "hellcat redeye 2021"
24 | myCar.price = "84,000$"
25 |
26 | fmt.Println(myCar.name)
27 |
28 | // or we can declare and set values with different
29 | // way...
30 | yourCar := car{
31 | "M7",
32 | "BMW",
33 | "5.4L twin turbo 550HP 682NM",
34 | "120,000$",
35 | }
36 |
37 | fmt.Println(yourCar)
38 | }
39 |
--------------------------------------------------------------------------------
/Basics/17 - methods/methods.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // Go does not have classes. However, we can define
6 | // methods on types
7 | type users []string
8 |
9 | func main() {
10 | newUsers := users{"erfan", "john", "eminem", "mark"}
11 |
12 | // fmt.Println(newUsers)
13 | newUsers.logger()
14 | newUsers.custumLogger(2, 4)
15 |
16 | addedUsers := newUsers.addUser("erik")
17 | addedUsers.logger()
18 | addedUsers.length()
19 | }
20 |
21 | // A method is a function with a special receiver argument.
22 | func (u users) logger() {
23 | fmt.Println(u)
24 | }
25 |
26 | func (u users) custumLogger(from, to int) {
27 | fmt.Println(u[from:to])
28 | }
29 |
30 | func (u users) addUser(name string) users {
31 | list := u
32 | list = append(list, name)
33 |
34 | return list
35 | }
36 |
37 | func (u users) length() {
38 | fmt.Println(len(u))
39 | }
40 |
--------------------------------------------------------------------------------
/Basics/18 - pointers/pointers.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | type human []string
6 |
7 | func main() {
8 | humans := human{"erfan", "ali"}
9 | humans.update("john")
10 |
11 | fmt.Println(humans)
12 | // return ["erfan" , "ali"]
13 | // why????
14 |
15 | // Go is a pass by value language
16 | // what is the pass by value language?
17 | // pass by value language means that a copy
18 | // of the actual parameter's value made in memory
19 |
20 | // how a RAM works??
21 | // |address | value |
22 | // | 0001 | erfan |
23 | // | 0002 | []string{"erfan" , "ali"} |
24 |
25 | // Each box in your computer's memory can store
26 | // some data and each one of these little boxes
27 | // there are these little value containers has
28 | // some discrate address
29 |
30 | // newHumans := human{"erfan"}
31 | // so when we create this newHumans variable of
32 | // type human go will create that slice of string
33 | // it will then go to the local memory on our
34 | // local machine
35 | // | address | value |
36 | // | 0001 | ["erfan"] |
37 |
38 | // what happen when we call this update("john") func?
39 | // whenever we pass some value into a function
40 | // will take that value its going to copy all of
41 | // that data inside that slice of string and then
42 | // place it inside of new some new container inside of
43 | // computer memory...
44 | // | address | value |
45 | // | 0001 | ["erfan"] |
46 | // | 0002 | ["erfan" , "update"] |
47 |
48 | // we are actually not updating the original
49 | // slice of string.. we are updating the copy
50 | // how do we rectify this issue??
51 | // we should use Pointers to solve this problem
52 |
53 | // func (h *human) update(name string) {
54 | // h = append(h , name)
55 | // }
56 |
57 | // we solve the problem...
58 |
59 | // how we can find the pointer of variable?
60 | // x := "erfan"
61 | // pointerX := &x
62 | // pointerX variable contain the x variable
63 | // pointer address in memory
64 |
65 | // how we can receive pointer value in func?
66 | x := 1
67 | fmt.Println("initial: ", x)
68 | // return 1
69 |
70 | toZero(x)
71 | fmt.Println("to zero without using pointer: ", x)
72 | // return 1
73 | // becuase change the copy variable in memory
74 |
75 | toZeroWithPointer(&x)
76 | fmt.Println("to zero with pointer: ", x)
77 | // return 0
78 | // becuase change the original variable in memory
79 |
80 | // &Variable means give me the memory address
81 | // *Pointer means give me the value this memory
82 | // address is pointing at
83 |
84 | // Value types
85 | // Use pointers to change these things in a function
86 | // Int , String , Struct , Bool , Float
87 |
88 | // Refrence types
89 | // Don't worry about pointers with these
90 | // Slice , Maps , Channels , Pointers , Functions
91 | }
92 |
93 | func toZero(value int) {
94 | value = 0
95 | }
96 |
97 | func toZeroWithPointer(value *int) {
98 | *value = 0
99 | }
100 |
101 | func (h human) update(name string) {
102 | h = append(h, name)
103 | }
104 |
--------------------------------------------------------------------------------
/Basics/19 - interface/interface.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | type human struct {
6 | name string
7 | }
8 |
9 | type animal struct {
10 | name string
11 | }
12 |
13 | type car struct {
14 | name string
15 | }
16 |
17 | type testInterface interface {
18 | // types contain Speak() method
19 | Speak() string
20 | }
21 |
22 | func main() {
23 | // Interfaces are named collections of method signatures.
24 | //For our example we’ll implement this interface on human and animal types.
25 | erfan := human{"erfan"}
26 | dog := animal{"pitter"}
27 | dodge := car{"dodge raptor"}
28 | // human and animal type contain Speak()
29 | // method so can access to log() function
30 |
31 | log(erfan)
32 | log(dog)
33 |
34 | // log(dodge)
35 | // Error: cannot use dodge (variable of type car)
36 | // as testInterface value in argument to log:
37 | // missing method Speak()
38 | fmt.Println(dodge)
39 | }
40 |
41 | // func log(h human){
42 | // fmt.Println(h.Speak())
43 | // }
44 | // func log(a animal) {
45 | // fmt.Println(a.Speak())
46 | // }
47 | // the interfaces solving this big problem on the top
48 | func log(in testInterface) {
49 | fmt.Println(in.Speak())
50 | }
51 |
52 | func (human) Speak() string {
53 | return "hellooooo"
54 | }
55 |
56 | func (animal) Speak() string {
57 | return "hop hop"
58 | }
59 |
--------------------------------------------------------------------------------
/Basics/2 - hello-world/README.md:
--------------------------------------------------------------------------------
1 | ## First program
2 |
3 | Our first program will print the classic "hello world"
4 |
5 | ## Run the code
6 |
7 | ```
8 | go run main.go
9 | ```
10 |
11 | Sometimes we’ll want to build our programs into binaries. We can do this using go build.
12 |
13 | ```
14 | go build main.go
15 | ```
16 |
17 | We can then execute the built binary directly.
18 |
--------------------------------------------------------------------------------
/Basics/2 - hello-world/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | fmt.Println("hello world!")
7 | }
8 |
--------------------------------------------------------------------------------
/Basics/20 - empty-interface/empty_interface.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main () {
6 | // The interface type that specifies zero methods
7 | // is known as the empty interface:
8 | // interface{}
9 |
10 | // An empty interface may hold values of any type.
11 | // (Every type implements at least zero methods.)
12 | // Empty interfaces are used by code that handles
13 | // values of unknown type
14 |
15 | unknownType(10)
16 | unknownType("hi")
17 | unknownType([]string{"john" , "rob"})
18 | }
19 |
20 | // Example
21 | // unknown type
22 | func unknownType(i interface{}) {
23 | switch theType := i.(type) {
24 | case int:
25 | fmt.Println("int")
26 |
27 | case string:
28 | fmt.Println("string")
29 |
30 | default:
31 | fmt.Println(theType)
32 | }
33 | }
--------------------------------------------------------------------------------
/Basics/21 - goroutines/GoRoutines.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ErfiDev/go-document/f563af721c630ebbbdd91096b5b62b42e49de4fa/Basics/21 - goroutines/GoRoutines.pptx
--------------------------------------------------------------------------------
/Basics/21 - goroutines/goroutines.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | )
7 |
8 | func main() {
9 | // A goroutine is a lightweight thread managed
10 | // by the Go runtime.
11 |
12 | // Example 1
13 | links := []string{
14 | "http://google.com",
15 | "http://golang.org",
16 | "http://github.com",
17 | "http://stackoverflow.com",
18 | }
19 | //
20 | //for _ , link := range links {
21 | // Example(link)
22 | //}
23 | // program is currently fetching one url at
24 | // the time waiting for that request complete
25 | // and then move on the next url
26 | // the impact of this is that if we have many
27 | // url and we want to fetch in our program
28 | // it'll take a long time to fetch every single one
29 | // because we're doing each one at the time
30 | // we want to fetch multiple request at the same
31 | // time actually how to make these request at the same
32 | // time? GoRoutines is the answer
33 |
34 |
35 | // when we launch the program golang automatically
36 | // create the MAIN ROUTINE
37 | // when the main routine reach to the first
38 | // line of ExampleOne func that wait for complete
39 | // then get to the next line of code
40 | // this bad because take the long time to fetching
41 | // one url at the time
42 | // we can solve this problem with create a new
43 | // child routine by `go` keyword
44 | // how to do?
45 | // if we want to create a new child routine
46 | // we should use `go` keyword before calling function
47 | // example: go Example(link)
48 |
49 | //for _ , link := range links {
50 | // go Example(link)
51 | //}
52 |
53 | // again we have the new problem
54 | // because the main routine end up faster than
55 | // other routine, and we can't see the result of these
56 | // child routines
57 | // golang has the solution for this big problem
58 | // CHANNELS
59 |
60 | // how they work?
61 | // look at the GoRoutines.pptx slide 4
62 |
63 | // we'll create a channel that we can use to say
64 | // hey has this routine finished, has this finished
65 | // and has this finished ok then the main routine
66 | // can exit.
67 |
68 | // Create channel syntax
69 | channel := make(chan string)
70 | // channel string
71 |
72 |
73 | for _ , link := range links {
74 | go Example(link , channel)
75 | }
76 |
77 | // listening to the channel
78 | for i := 0 ; i < len(links) ; i++ {
79 | fmt.Println(<- channel)
80 | }
81 | }
82 |
83 | // Example
84 | // receiving the channel as an argument
85 | func Example(link string , channel chan string) {
86 | _ , err := http.Get(link)
87 |
88 | if err != nil{
89 | // We will talk about nil in a few
90 | // chapters later
91 | fmt.Println(link , "is down")
92 | // sending message to channel with this `<-` syntax
93 | channel <- "is down"
94 | return
95 | }
96 |
97 | fmt.Println(link , "is up")
98 | channel <- "is up"
99 | }
100 |
--------------------------------------------------------------------------------
/Basics/22 - blank-identifier/blank_identifies.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | _ "os"
7 | // one of the blank identifier use case
8 | )
9 |
10 | // the blank identifier
11 |
12 | func main() {
13 | // The use of a blank identifier in a for range
14 | // loop is a special case of a general situation:
15 | // multiple assignment.
16 | // If an assignment requires multiple values on the
17 | // left side, but one of the values will not be used
18 | // by the program, a blank identifier on the
19 | // left-hand-side of the assignment avoids the need
20 | // to create a dummy variable and makes it clear
21 | // that the value is to be discarded. For instance,
22 | // when calling a function that returns a value and
23 | // an error, but only the error is important, use
24 | // the blank identifier to discard the irrelevant value.
25 |
26 | // Example 1
27 | users := []string{"erfan", "john", "tom", "dominic"}
28 |
29 | for _, value := range users {
30 | fmt.Println(value)
31 | }
32 |
33 | // Example 2
34 | _, err := ExampleTwo(19)
35 | if err != nil {
36 | fmt.Println(err)
37 | }
38 | }
39 |
40 | func ExampleTwo(i int) (string, interface{}) {
41 | if i < 18 {
42 | return "", errors.New("error")
43 | } else {
44 | return "ok", ""
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Basics/23 - defer/defer.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "os"
6 | )
7 |
8 | func main() {
9 | // Defer is used to ensure that a function call is
10 | // performed later in a program’s execution, usually
11 | // for purposes of cleanup. defer is often used where
12 | // e.g. ensure and finally would be used in other
13 | // languages.
14 |
15 | // Suppose we wanted to create a file, write to it,
16 | // and then close when we’re done. Here’s how we could
17 | // do that with defer.
18 |
19 | // Immediately after getting a file object with
20 | // createFile, we defer the closing of that file
21 | // with closeFile. This will be executed at the end
22 | // of the enclosing function (main), after writeFile
23 | // has finished.
24 |
25 | file , err := os.Create("test.txt")
26 | defer file.Close()
27 | // if we remove the defer keyword we receive the big error
28 | // called : file already closed
29 | if err != nil {
30 | log.Fatal(err)
31 | }
32 |
33 | writeFile(file , "hi")
34 | }
35 |
36 | func writeFile(file *os.File , data string) {
37 | toByteSlice := []byte(data)
38 | _ , err := file.Write(toByteSlice)
39 | if err != nil {
40 | panic(err)
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Basics/24 - panic/panic.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {
4 | // A panic typically means something went unexpectedly
5 | // wrong. Mostly we use it to fail fast on errors that
6 | // shouldn’t occur during normal operation, or that we
7 | // aren’t prepared to handle gracefully.
8 |
9 | // if the error is unrecoverable sometimes the
10 | // program simply can't continue
11 | // for this purpose there is the built-in function
12 | // Panic() that is effect creates a run time error
13 | // that will stop the program
14 |
15 | myPanic()
16 |
17 |
18 | // this is only an example but real program or library
19 | // should avoid panic()
20 | }
21 |
22 | func myPanic() {
23 | panic("we have the error :)")
24 | }
25 |
--------------------------------------------------------------------------------
/Basics/25 - recover/recover.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func mayPanic() {
6 | panic("a problem")
7 | }
8 |
9 | func main() {
10 | // Go makes it possible to recover from a panic, by
11 | // using the recover built-in function. A recover
12 | // can stop a panic from aborting the program and let
13 | // it continue with execution instead.
14 |
15 | // An example of where this can be useful: a server
16 | // wouldn’t want to crash if one of the client
17 | // connections exhibits a critical error. Instead,
18 | // the server would want to close that connection and
19 | // continue serving other clients. In fact, this is
20 | // what Go’s net/http does by default for HTTP servers.
21 |
22 | defer func() {
23 | if r := recover(); r != nil {
24 |
25 | fmt.Println("Recovered. Error:\n", r)
26 | }
27 | }()
28 |
29 | mayPanic()
30 |
31 | fmt.Println("After mayPanic()")
32 | }
33 |
--------------------------------------------------------------------------------
/Basics/26 - select/select.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "time"
6 | )
7 |
8 | func main() {
9 | // The select statement lets a goroutine wait on
10 | // multiple communication operations.
11 | // A select blocks until one of its cases can run,
12 | // then it executes that case. It chooses one at
13 | // random if multiple are ready.
14 | chan1, chan2 := make(chan int), make(chan string)
15 |
16 | go NewRoutine(chan1, chan2)
17 |
18 | for {
19 | select {
20 | case msg := <-chan1:
21 | fmt.Println(msg)
22 |
23 | case msgEnd := <-chan2:
24 | fmt.Println(msgEnd)
25 | return
26 | }
27 | }
28 | }
29 |
30 | func NewRoutine(c1 chan int, c2 chan string) {
31 | for i := 0; i < 5; i++ {
32 | c1 <- i
33 | }
34 |
35 | time.Sleep(1 * time.Second)
36 | c2 <- "end"
37 | }
38 |
--------------------------------------------------------------------------------
/Basics/27 - nil/nil.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | type person struct {
6 | name string
7 | }
8 |
9 | func main() {
10 | // Are nil and null the same thing?
11 | // Coming from Java or other programming language
12 | // background you might think they are but they
13 | // partly are the same yet somewhat different.
14 | // nil is a predeclared identifier in Go that
15 | // represents zero values for pointers, interfaces,
16 | // channels, maps, slices and function types. nil being
17 | // the zero value of pointers and interfaces, uninitialized
18 | // pointers and interfaces will be nil.So does that mean a
19 | // string can’t be nil, yes you are right, a string doesn’t
20 | // qualify to be either of the above-mentioned types
21 | // and hence can’t be assigned nil.
22 |
23 | // a := nil
24 | // This will be a compile-time error use of untyped nilsince
25 | // nil is untyped and the only untyped value that doesn’t
26 | // have default type and the compiler has no idea which
27 | // type it has to assign to a.
28 |
29 | erfan := getPerson()
30 | fmt.Println(erfan)
31 |
32 | var nilSlice []string = nil
33 | fmt.Println(nilSlice)
34 |
35 | var nilMap map[string]string = nil
36 | fmt.Println(nilMap)
37 | }
38 |
39 | func getPerson() *person {
40 | return nil
41 | }
42 |
--------------------------------------------------------------------------------
/Basics/28 - packages/controller/controller.go:
--------------------------------------------------------------------------------
1 | package controller
2 |
3 | import "fmt"
4 |
5 | func LogController() {
6 | fmt.Println("log controller func")
7 | }
8 |
--------------------------------------------------------------------------------
/Basics/28 - packages/go.mod:
--------------------------------------------------------------------------------
1 | module package-testing
2 |
3 | go 1.16
4 |
--------------------------------------------------------------------------------
/Basics/28 - packages/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "package-testing/controller"
4 |
5 | func main() {
6 | // how we can create a package and use??
7 |
8 | // step 1: go mod init something....
9 | // step 2: create a folder called anything
10 | // step 3: import in main.go file or etc and use them
11 | controller.LogController()
12 | }
13 |
--------------------------------------------------------------------------------
/Basics/3 - go-cli/README.md:
--------------------------------------------------------------------------------
1 | # Golang CLI
2 |
3 | How do we run the code in our project?
4 |
5 | ## Go build
6 |
7 | Compile a bunch of GO source code files
8 |
9 | ## Go run
10 |
11 | Compiles and executes one or two files
12 |
13 | ## Go fmt
14 |
15 | Formats all the codes in each file in current directory
16 |
17 | ## Go install
18 |
19 | Compiles and installs a GO package
20 |
21 | ## Go get
22 |
23 | Downloads the raw source code of someone else's package
24 |
25 | ## Go test
26 |
27 | Run any tests in associated with the current project
28 |
--------------------------------------------------------------------------------
/Basics/4 - basic-questions/README.md:
--------------------------------------------------------------------------------
1 | # Basic Questions
2 |
3 | ## what does "package main" mean
4 |
5 | when we see the word package in go
6 | we can think of a package as being like a project
7 | or a workspace
8 | a package is a collections of common source code files
9 | so a package can have many related file inside of it each
10 | file ending with a file extension of .go
11 |
12 | the only requirement for every file inside of the package
13 | is at the very first line of each file must declare the package that it blongs to
14 |
15 | two types of packages
16 |
17 | - Executable
18 | - Reusable
19 |
20 |
21 |
22 |
23 | ## what does "import" mean
24 |
25 | the import statement is used to give our package
26 |
27 |
28 | ```
29 | import "fmt"
30 | ```
31 |
32 |
33 | so saying import fmt specificly means give my package main access to all of the code and all the functionality that is contained inside of other package called fmt
34 |
35 |
36 |
37 |
38 | - fmt the name of the standard library package that is includes with the go programming language by default the fmt package is used to print out a lot of different information specificly to the terminal
39 | just give you a better sense of debugging and stuff like that
40 |
41 |
42 |
43 |
44 | ## what is that "func" thing
45 |
46 | func is a short of the function in golang
47 |
48 | ```
49 | func main(){
50 | // code
51 | }
52 | ```
53 |
54 |
55 |
56 | 1. func is a function keyword
57 | 2. main is a function name
58 | 3. () is a function arguments
59 | 4. {} this is a function body
60 |
--------------------------------------------------------------------------------
/Basics/4 - basic-questions/main.go:
--------------------------------------------------------------------------------
1 | // package declare
2 | package main
3 |
4 | // import statement
5 | import "fmt"
6 |
7 | // func main
8 | func main() {
9 | fmt.Println("hello world")
10 | }
11 |
--------------------------------------------------------------------------------
/Basics/5 - values/values.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // Data types in golang
6 | func main() {
7 | // Integer types
8 | // Default value for integer types = 0
9 | var age int = 27
10 | var x int
11 | fmt.Println(x)
12 | // x variable return the 0
13 |
14 | // Floating types
15 | // Default value for float types = 0
16 | var pi float64 = 3.14
17 |
18 | // String types
19 | // Default value for string types = ""
20 | var name string = "erfan"
21 | var family string
22 | fmt.Println(family)
23 | // family variable return the ""
24 |
25 | // Boolean types
26 | // Default value for boolean types = false
27 | var human bool = true
28 | var toggle bool
29 | fmt.Println(toggle)
30 | // toggle variable return the false value
31 |
32 | fmt.Println("my age: ", age)
33 | fmt.Println("my name: ", name)
34 | fmt.Println("im a human? ", human)
35 | fmt.Println("pi number: ", pi)
36 | }
37 |
--------------------------------------------------------------------------------
/Basics/6 - variables/variables.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | // has two way to declare a variable in go language
7 |
8 | // first
9 | var name string = "erfan"
10 | var age = 17
11 |
12 | // second
13 | email := "erfanhanifezade@gmail.com"
14 |
15 | fmt.Println("my name is: ", name)
16 | fmt.Println("my age: ", age)
17 | fmt.Println("and my email: ", email)
18 | }
19 |
--------------------------------------------------------------------------------
/Basics/7 - constant/constant.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | const DATABASE_URL = "mongodb://localhost:25408"
6 |
7 | func main() {
8 | // Go supports constants of character, string,
9 | // boolean, and numeric values.
10 |
11 | fmt.Println(DATABASE_URL)
12 |
13 | const pi = 3.14
14 | fmt.Println(pi)
15 | }
16 |
--------------------------------------------------------------------------------
/Basics/8 - for/for.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | // for is Go’s only looping construct.
7 | // Here are some basic types of for loops.
8 |
9 | // The most basic type, with a single condition.
10 | i := 0
11 | for i <= 5 {
12 | fmt.Println(i)
13 | i++
14 | }
15 |
16 | // The classic initial/condition/update for loop
17 | for j := 0; j <= 10; j++ {
18 | fmt.Println(j)
19 | }
20 |
21 | // for without a condition will loop repeatedly
22 | // until you break out of the loop or return from
23 | // the enclosing function.
24 | for {
25 | fmt.Println("for without a condition")
26 | break
27 | // or return for break out the loop
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Basics/9 - if-else/if_else.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | // golang can make choices with data.
7 | // This data (variables) are used with a condition:
8 | // if statements start with a condition
9 | // A condition may be (x > 3), (y < 4), (weather = rain).
10 | // Only if a condition is true, code is executed.
11 |
12 | x := 3
13 |
14 | // Condition
15 | if x > 10 {
16 | fmt.Println("x is higher than 10")
17 | }
18 | // this condition is not working becuase
19 | // condition is false
20 |
21 | // but this condition is working becuase
22 | // consition is true
23 | if x == 3 {
24 | fmt.Println("condition working")
25 | }
26 |
27 | // You can execute a codeblock if a condition
28 | // is not true
29 | a := 10
30 |
31 | if a > 20 {
32 | fmt.Println("a variable higher than 20")
33 | } else {
34 | fmt.Println("a variable is lower than 20")
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Basics/README.md:
--------------------------------------------------------------------------------
1 | # Basics Sections
2 |
3 | 0. About go language
4 | 1. Installation
5 | 2. Hello-world program
6 | 3. Golang cli commands
7 | 4. Basic questions answers
8 | 5. values
9 | 6. variables
10 | 7. constant
11 | 8. for loop
12 | 9. if/else
13 | 10. switch
14 | 11. arrays
15 | 12. slices
16 | 13. maps
17 | 14. range
18 | 15. functions
19 | 16. struct
20 | 17. methods
21 | 18. pointer
22 | 19. interfaces
23 | 20. empty-interfaces
24 | 21. goroutines
25 | 22. blank-identifier
26 | 23. defer
27 | 24. panic
28 | 25. recover
29 | 26. select
30 | 27. nil
31 | 28. packages
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Go document
2 |
3 | a GO language free and open-source document for learning from zero level
4 |
5 |
6 | Please publish and collaborate OPEN-SOURCE
7 |
8 | ## Sections
9 |
10 | - [Basics](https://github.com/ErfiDev/go-document/tree/master/Basics)
11 | - [Web server](https://github.com/ErfiDev/go-document/tree/master/web-server)
12 | - [Testing](https://github.com/ErfiDev/go-document/tree/master/testing)
13 | - [Resource](https://github.com/ErfiDev/go-document/tree/master/resource)
14 | - [Advanced](https://github.com/ErfiDev/go-document/tree/master/advanced)
15 |
--------------------------------------------------------------------------------
/advanced/bitwise-operators/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "math/rand"
6 | )
7 |
8 | func main() {
9 | // The Go programming language supports several
10 | // bitwise operators including the followings:
11 |
12 | // & bitwise AND
13 | // | bitwise OR
14 | // ^ bitwise XOR
15 | // &^ AND NOT
16 | // << left shift
17 | // >> right shift
18 |
19 | // &
20 | // In Go, the & operator performs the bitwise AND
21 | // operation between two integer operands
22 | // The AND operator has the nice side effect of
23 | // selectively clearing bits of an integer value to
24 | // zero. For instance, we can use the & operator to
25 | // clear (set to zero) the last 4 least significant
26 | // bits (LSB) to all zeros.
27 |
28 | var x uint8 = 0xAC // x = 10101100
29 | x = x & 0xF0 // x = 10100000
30 | // or x &= 0xF0
31 |
32 | // Another neat trick you can do with & operator is
33 | // to test whether a number is odd or even. This works
34 | // because a number is odd when its least significant
35 | // bit is set (equal 1). We can use the & operator
36 | // apply a bitwise AND operation to an integer the
37 | // value 1. If the result is 1, then the original
38 | // number is odd.
39 |
40 | for x := 0; x < 100; x++ {
41 | num := rand.Int()
42 | if num&1 == 1 {
43 | fmt.Printf("%d is odd\n", num)
44 | } else {
45 | fmt.Printf("%d is even\n", num)
46 | }
47 | }
48 |
49 | var odd int = 7
50 | var even int = 8
51 | fmt.Println("example: how it work:", odd&1)
52 | // if return 1 value is odd
53 | // and if return 0 value is even
54 | fmt.Println("example: how it work:", even&1)
55 |
56 | // |
57 | var value1, value2 int = 5, 3
58 | result := value1 | value2
59 | fmt.Println("5 | 3 = ", result)
60 | // Takes two numbers as operands and does OR on every
61 | // bit of two numbers. The result of OR is 1 any of
62 | // the two bits is 1.
63 |
64 | // ^
65 | // Takes two numbers as operands and does XOR on every
66 | // bit of two numbers. The result of XOR is 1 if the
67 | // two bits are different.
68 | result = value1 ^ value2
69 | fmt.Println("5 ^ 3 = ", result)
70 |
71 | // <<
72 | // Takes two numbers, left shifts the bits of the
73 | // first operand, the second operand decides the
74 | // number of places to shift.
75 | result = 5 << 3
76 | // 5 << 1 === 10
77 | // 5 << 2 === 20
78 | // 5 << 3 === 40
79 | fmt.Println("5 << 3 = ", result)
80 |
81 | // >>
82 | // Takes two numbers, right shifts the bits of the
83 | // first operand, the second operand decides the number
84 | // of places to shift.
85 | result = 5 >> 1
86 | fmt.Println("5 >> 1 = ", result)
87 |
88 | // &^
89 | // This is a bit clear operator.
90 | result = 5 &^ 1
91 | fmt.Println("5 &^ 1 = ", result)
92 | }
93 |
--------------------------------------------------------------------------------
/advanced/char/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | // golang does not have any datatype of `char`
7 |
8 | // but we can use `byte or rune` to represent a single character
9 |
10 | // byte is used for repersent of ASCII characters
11 | // and rune is used for ALL UNICODE characters
12 |
13 | // to create either a byte or rune we use single quotes
14 |
15 | var E = 'E'
16 |
17 | fmt.Printf("the type of E is %T\n", E)
18 | fmt.Println(string(E))
19 |
20 | // while declaring byte we have to specify the type,
21 | // if we don't specify the type, then the default
22 | // type is meant as a rune
23 |
24 | var A byte = 'A'
25 | fmt.Printf("type of A = %T\n", A)
26 | fmt.Println(string(A))
27 |
28 | // rune = int32
29 | // byte = uint8
30 | }
31 |
--------------------------------------------------------------------------------
/advanced/concurrency/dining_philosophers/dining_philosophers.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "sync"
6 | "time"
7 | )
8 |
9 | var philosophers = []string{"a", "b", "c", "d", "e"}
10 | var wg sync.WaitGroup
11 |
12 | func main() {
13 | wg.Add(len(philosophers))
14 |
15 | leftHand := new(sync.Mutex)
16 |
17 | for _, ph := range philosophers {
18 | rightHand := new(sync.Mutex)
19 |
20 | go Eat(ph, rightHand, leftHand)
21 |
22 | leftHand = rightHand
23 | }
24 |
25 | wg.Wait()
26 | }
27 |
28 | func Eat(name string, rightHand, leftHand *sync.Mutex) {
29 | defer wg.Done()
30 |
31 | fmt.Printf("%s seate\n", name)
32 |
33 | rightHand.Lock()
34 | leftHand.Lock()
35 |
36 | fmt.Printf("%s is eating\n", name)
37 | time.Sleep(time.Duration(2) * time.Second)
38 |
39 | rightHand.Unlock()
40 | leftHand.Unlock()
41 |
42 | fmt.Printf("%s has left the table!\n", name)
43 | }
44 |
--------------------------------------------------------------------------------
/advanced/concurrency/go.mod:
--------------------------------------------------------------------------------
1 | module concurrency
2 |
3 | go 1.18
4 |
5 | require github.com/fatih/color v1.13.0
6 |
7 | require (
8 | github.com/mattn/go-colorable v0.1.13 // indirect
9 | github.com/mattn/go-isatty v0.0.16 // indirect
10 | golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect
11 | )
12 |
--------------------------------------------------------------------------------
/advanced/concurrency/go.sum:
--------------------------------------------------------------------------------
1 | github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
2 | github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
3 | github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
4 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
5 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
6 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
7 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
8 | github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
9 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
10 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
11 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
12 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
13 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
14 | golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 h1:Sx/u41w+OwrInGdEckYmEuU5gHoGSL4QbDz3S9s6j4U=
15 | golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
16 |
--------------------------------------------------------------------------------
/advanced/concurrency/producer_consumer/producer_consumer.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "math/rand"
6 | "time"
7 |
8 | "github.com/fatih/color"
9 | )
10 |
11 | const NumberOfPizzas = 10
12 |
13 | var pizzasMade, pizzasFailed, total int
14 |
15 | // Producer is a type for structs that holds two channels: one for pizzas, with all
16 | // information for a given pizza order including whether it was made
17 | // successfully, and another to handle end of processing (when we quit the channel)
18 | type Producer struct {
19 | data chan PizzaOrder
20 | quit chan chan error
21 | }
22 |
23 | // PizzaOrder is a type for structs that describes a given pizza order. It has the order
24 | // number, a message indicating what happened to the order, and a boolean
25 | // indicating if the order was successfully completed.
26 | type PizzaOrder struct {
27 | pizzaNumber int
28 | message string
29 | success bool
30 | }
31 |
32 | // Close is simply a method of closing the channel when we are done with it (i.e.
33 | // something is pushed to the quit channel)
34 | func (p *Producer) Close() error {
35 | ch := make(chan error)
36 | p.quit <- ch
37 | return <-ch
38 | }
39 |
40 | // makePizza attempts to make a pizza. We generate a random number from 1-12,
41 | // and put in two cases where we can't make the pizza in time. Otherwise,
42 | // we make the pizza without issue. To make things interesting, each pizza
43 | // will take a different length of time to produce (some pizzas are harder than others).
44 | func makePizza(pizzaNumber int) *PizzaOrder {
45 | pizzaNumber++
46 | if pizzaNumber <= NumberOfPizzas {
47 | delay := rand.Intn(5) + 1
48 | fmt.Printf("Received order #%d!\n", pizzaNumber)
49 |
50 | rnd := rand.Intn(12) + 1
51 | msg := ""
52 | success := false
53 |
54 | if rnd < 5 {
55 | pizzasFailed++
56 | } else {
57 | pizzasMade++
58 | }
59 | total++
60 |
61 | fmt.Printf("Making pizza #%d. It will take %d seconds....\n", pizzaNumber, delay)
62 | // delay for a bit
63 | time.Sleep(time.Duration(delay) * time.Second)
64 |
65 | if rnd <= 2 {
66 | msg = fmt.Sprintf("*** We ran out of ingredients for pizza #%d!", pizzaNumber)
67 | } else if rnd <= 4 {
68 | msg = fmt.Sprintf("*** The cook quit while making pizza #%d!", pizzaNumber)
69 | } else {
70 | success = true
71 | msg = fmt.Sprintf("Pizza order #%d is ready!", pizzaNumber)
72 | }
73 |
74 | p := PizzaOrder{
75 | pizzaNumber: pizzaNumber,
76 | message: msg,
77 | success: success,
78 | }
79 |
80 | return &p
81 |
82 | }
83 |
84 | return &PizzaOrder{
85 | pizzaNumber: pizzaNumber,
86 | }
87 | }
88 |
89 | // pizzeria is a goroutine that runs in the background and
90 | // calls makePizza to try to make one order each time it iterates through
91 | // the for loop. It executes until it receives something on the quit
92 | // channel. The quit channel does not receive anything until the consumer
93 | // sends it (when the number of orders is greater than or equal to the
94 | // constant NumberOfPizzas).
95 | func pizzeria(pizzaMaker *Producer) {
96 | // keep track of which pizza we are making
97 | var i = 0
98 |
99 | // this loop will continue to execute, trying to make pizzas,
100 | // until the quit channel receives something.
101 | for {
102 | currentPizza := makePizza(i)
103 | if currentPizza != nil {
104 | i = currentPizza.pizzaNumber
105 | select {
106 | // we tried to make a pizza (we send something to the data channel -- a chan PizzaOrder)
107 | case pizzaMaker.data <- *currentPizza:
108 |
109 | // we want to quit, so send pizzMaker.quit to the quitChan (a chan error)
110 | case quitChan := <-pizzaMaker.quit:
111 | // close channels
112 | close(pizzaMaker.data)
113 | close(quitChan)
114 | return
115 | }
116 | }
117 | }
118 | }
119 |
120 | func main() {
121 | // seed the random number generator
122 | rand.Seed(time.Now().UnixNano())
123 |
124 | // print out a message
125 | color.Cyan("The Pizzeria is open for business!")
126 | color.Cyan("----------------------------------")
127 |
128 | // create a producer
129 | pizzaJob := &Producer{
130 | data: make(chan PizzaOrder),
131 | quit: make(chan chan error),
132 | }
133 |
134 | // run the producer in the background
135 | go pizzeria(pizzaJob)
136 |
137 | // create and run consumer
138 | for i := range pizzaJob.data {
139 | if i.pizzaNumber <= NumberOfPizzas {
140 | if i.success {
141 | color.Green(i.message)
142 | color.Green("Order #%d is out for delivery!", i.pizzaNumber)
143 | } else {
144 | color.Red(i.message)
145 | color.Red("The customer is really mad!")
146 | }
147 | } else {
148 | color.Cyan("Done making pizzas...")
149 | err := pizzaJob.Close()
150 | if err != nil {
151 | color.Red("*** Error closing channel!", err)
152 | }
153 | }
154 | }
155 |
156 | // print out the ending message
157 | color.Cyan("-----------------")
158 | color.Cyan("Done for the day.")
159 |
160 | color.Cyan("We made %d pizzas, but failed to make %d, with %d attempts in total.", pizzasMade, pizzasFailed, total)
161 |
162 | switch {
163 | case pizzasFailed > 9:
164 | color.Red("It was an awful day...")
165 | case pizzasFailed >= 6:
166 | color.Red("It was not a very good day...")
167 | case pizzasFailed >= 4:
168 | color.Yellow("It was an okay day....")
169 | case pizzasFailed >= 2:
170 | color.Yellow("It was a pretty good day!")
171 | default:
172 | color.Green("It was a great day!")
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/advanced/concurrency/sleeping_barber/sleeping_barber.go:
--------------------------------------------------------------------------------
1 | // This is a simple demonstration of how to solve the Sleeping Barber dilemma, a classic computer science problem
2 | // which illustrates the complexities that arise when there are multiple operating system processes. Here, we have
3 | // a finite number of barbers, a finite number of seats in a waiting room, a fixed length of time the barbershop is
4 | // open, and clients arriving at (roughly) regular intervals. When a barber has nothing to do, he or she checks the
5 | // waiting room for new clients, and if one or more is there, a haircut takes place. Otherwise, the barber goes to
6 | // sleep until a new client arrives. So the rules are as follows:
7 | //
8 | // - if there are no customers, the barber falls asleep in the chair
9 | // - a customer must wake the barber if he is asleep
10 | // - if a customer arrives while the barber is working, the customer leaves if all chairs are occupied and
11 | // sits in an empty chair if it's available
12 | // - when the barber finishes a haircut, he inspects the waiting room to see if there are any waiting customers
13 | // and falls asleep if there are none
14 | // - shop can stop accepting new clients at closing time, but the barbers cannot leave until the waiting room is
15 | // empty
16 | // - after the shop is closed and there are no clients left in the waiting area, the barber
17 | // goes home
18 | //
19 | // The Sleeping Barber was originally proposed in 1965 by computer science pioneer Edsger Dijkstra.
20 | //
21 | // The point of this problem, and its solution, was to make it clear that in a lot of cases, the use of
22 | // semaphores (mutexes) is not needed.
23 | package main
24 |
25 | import (
26 | "fmt"
27 | "math/rand"
28 | "time"
29 |
30 | "github.com/fatih/color"
31 | )
32 |
33 | // variables
34 | var seatingCapacity = 10
35 | var arrivalRate = 100
36 | var cutDuration = 1000 * time.Millisecond
37 | var timeOpen = 10 * time.Second
38 |
39 | func main() {
40 | // seed our random number generator
41 | rand.Seed(time.Now().UnixNano())
42 |
43 | // print welcome message
44 | color.Yellow("The Sleeping Barber Problem")
45 | color.Yellow("---------------------------")
46 |
47 | // create channels if we need any
48 | clientChan := make(chan string, seatingCapacity)
49 | doneChan := make(chan bool)
50 |
51 | // create the barbershop
52 | shop := BarberShop{
53 | ShopCapacity: seatingCapacity,
54 | HairCutDuration: cutDuration,
55 | NumberOfBarbers: 0,
56 | ClientsChan: clientChan,
57 | BarbersDoneChan: doneChan,
58 | Open: true,
59 | }
60 |
61 | color.Green("The shop is open for the day!")
62 |
63 | // add barbers
64 | shop.addBarber("Frank")
65 |
66 | // start the barbershop as a goroutine
67 | shopClosing := make(chan bool)
68 | closed := make(chan bool)
69 |
70 | go func() {
71 | <-time.After(timeOpen)
72 | shopClosing <- true
73 | shop.closeShopForDay()
74 | closed <- true
75 | }()
76 |
77 | // add clients
78 | i := 1
79 |
80 | go func() {
81 | for {
82 | // get a random number with average arrival rate
83 | randomMillseconds := rand.Int() % (2 * arrivalRate)
84 | select {
85 | case <-shopClosing:
86 | return
87 | case <-time.After(time.Millisecond * time.Duration(randomMillseconds)):
88 | shop.addClient(fmt.Sprintf("Client #%d", i))
89 | i++
90 | }
91 | }
92 | }()
93 |
94 | // block until the barbershop is closed
95 | <-closed
96 | }
97 |
98 | type BarberShop struct {
99 | ShopCapacity int
100 | HairCutDuration time.Duration
101 | NumberOfBarbers int
102 | BarbersDoneChan chan bool
103 | ClientsChan chan string
104 | Open bool
105 | }
106 |
107 | func (shop *BarberShop) addBarber(barber string) {
108 | shop.NumberOfBarbers++
109 |
110 | go func() {
111 | isSleeping := false
112 | color.Yellow("%s goes to the waiting room to check for clients.", barber)
113 |
114 | for {
115 | // if there are no clients, the barber goes to sleep
116 | if len(shop.ClientsChan) == 0 {
117 | color.Yellow("There is nothing to do, so %s takes a nap.", barber)
118 | isSleeping = true
119 | }
120 |
121 | client, shopOpen := <-shop.ClientsChan
122 |
123 | if shopOpen {
124 | if isSleeping {
125 | color.Yellow("%s wakes %s up.", client, barber)
126 | isSleeping = false
127 | }
128 | // cut hair
129 | shop.cutHair(barber, client)
130 | } else {
131 | // shop is closed, so send the barber home and close this goroutine
132 | shop.sendBarberHome(barber)
133 | return
134 | }
135 | }
136 | }()
137 | }
138 |
139 | func (shop *BarberShop) cutHair(barber, client string) {
140 | color.Green("%s is cutting %s's hair.", barber, client)
141 | time.Sleep(shop.HairCutDuration)
142 | color.Green("%s is finished cutting %s's hair.", barber, client)
143 | }
144 |
145 | func (shop *BarberShop) sendBarberHome(barber string) {
146 | color.Cyan("%s is going home.", barber)
147 | shop.BarbersDoneChan <- true
148 | }
149 |
150 | func (shop *BarberShop) closeShopForDay() {
151 | color.Cyan("Closing shop for the day.")
152 |
153 | close(shop.ClientsChan)
154 | shop.Open = false
155 |
156 | for a := 1; a <= shop.NumberOfBarbers; a++ {
157 | <-shop.BarbersDoneChan
158 | }
159 |
160 | close(shop.BarbersDoneChan)
161 |
162 | color.Green("---------------------------------------------------------------------")
163 | color.Green("The barbershop is now closed for the day, and everyone has gone home.")
164 | }
165 |
166 | func (shop *BarberShop) addClient(client string) {
167 | // print out a message
168 | color.Green("*** %s arrives!", client)
169 |
170 | if shop.Open {
171 | select {
172 | case shop.ClientsChan <- client:
173 | color.Yellow("%s takes a seat in the waiting room.", client)
174 | default:
175 | color.Red("The waiting room is full, so %s leaves.", client)
176 | }
177 | } else {
178 | color.Red("The shop is already closed, so %s leaves!", client)
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/advanced/context/context.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "time"
7 | )
8 |
9 | func main() {
10 | // In Go servers, each incoming request is handled
11 | // in its own goroutine. Request handlers often start
12 | // additional goroutines to access backends such as
13 | // databases and RPC services. The set of goroutines
14 | // working on a request typically needs access to
15 | // request-specific values such as the identity of
16 | // the end user, authorization tokens, and the
17 | // request’s deadline. When a request is canceled or
18 | // times out, all the goroutines working on that
19 | // request should exit quickly so the system can
20 | // reclaim any resources they are using.
21 | // At Google, we developed a context package that
22 | // makes it easy to pass request-scoped values,
23 | // cancelation signals, and deadlines across API
24 | // boundaries to all the goroutines involved in
25 | // handling a request. The package is publicly
26 | // available as context. This article describes how
27 | // to use the package and provides a complete working
28 | // example.
29 |
30 | shortDuration := 1 * time.Millisecond
31 |
32 | ctx, cancel := context.WithTimeout(context.Background(), shortDuration)
33 | defer cancel()
34 |
35 | select {
36 | case <-time.After(1 * time.Second):
37 | fmt.Println("after one second")
38 |
39 | case <-ctx.Done():
40 | fmt.Println(ctx.Err())
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/advanced/deadlock/deadlock.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "sync"
6 | "time"
7 | )
8 |
9 | /*
10 | Deadlock:
11 | occur when two or more threads are blocked,
12 | waiting for each other to release a response.
13 | */
14 |
15 | type Value struct {
16 | mu sync.Mutex
17 | v int
18 | }
19 |
20 | func sum(v1, v2 *Value, wg *sync.WaitGroup) {
21 | defer wg.Done()
22 |
23 | v1.mu.Lock()
24 | defer v1.mu.Unlock()
25 |
26 | time.Sleep(time.Second * 2)
27 |
28 | v2.mu.Lock()
29 | defer v2.mu.Unlock()
30 |
31 | fmt.Println("sum: ", v1.v+v2.v)
32 | }
33 |
34 | func main() {
35 | wg := new(sync.WaitGroup)
36 |
37 | v1, v2 := new(Value), new(Value)
38 |
39 | wg.Add(2)
40 |
41 | go sum(v1, v2, wg)
42 | go sum(v2, v1, wg)
43 |
44 | wg.Wait()
45 | }
46 |
47 | /*
48 | What happend?
49 |
50 | our first call to `sum` lock `a` and then attempts
51 | to lock `b` but in the meantime our second call to
52 | `sum` has locked `b` and has attempts to lock `a`.
53 | both goroutines wait infinitely on each other.
54 | */
55 |
--------------------------------------------------------------------------------
/advanced/iota/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | const (
6 | erfan = iota
7 | john
8 | robert
9 | leo
10 | )
11 |
12 | func main() {
13 | // Iota is a useful concept for creating incrementing
14 | // constants in Go. However, there are several areas
15 | // where iota may not be appropriate to use.
16 | // This article will cover several different ways in
17 | // which you can use iota, and tips on where to be
18 | // cautious with it's use.
19 | fmt.Println(erfan, john, robert, leo)
20 |
21 | // Skipping values
22 | const (
23 | zero int = iota
24 | one
25 | _
26 | three
27 | )
28 |
29 | fmt.Println(zero, one, three)
30 |
31 | // Advanced Iota Usage
32 | // Because of the way iota automatically increments,
33 | // we can use it to calculate more advanced scenarios.
34 | // For instance, if you have worked with bitmasks
35 | // Iota can be used to quickly create the correct
36 | // values by using the bit shift operator.
37 | const (
38 | read = 1 << iota // 00000001 = 1
39 | write // 00000010 = 2
40 | remove // 00000100 = 4
41 |
42 | // admin will have all of the permissions
43 | admin = read | write | remove
44 | )
45 | fmt.Println(read, write, remove, admin)
46 |
47 | // Memory size
48 | const (
49 | _ = 1 << (iota * 10) // ignore the first value
50 | KB // decimal: 1024 -> binary 00000000000000000000010000000000
51 | MB // decimal: 1048576 -> binary 00000000000100000000000000000000
52 | GB // decimal: 1073741824 -> binary 01000000000000000000000000000000
53 | )
54 | fmt.Println(KB, MB, GB)
55 | }
56 |
--------------------------------------------------------------------------------
/advanced/keywords/fallthrough.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | // fallthrough keyword is used in switch
7 | // statement in golang. This keyword is used
8 | // in switch case block. If the fallthrough
9 | // keyword is present in the case block, then
10 | // it will transfer control to the next case
11 | // even though the current case might have
12 | // matched.
13 |
14 | val := 8
15 |
16 | switch {
17 | case val < 10:
18 | fmt.Println("is less than 10")
19 | fallthrough
20 |
21 | case val < 20:
22 | fmt.Println("is less than 20")
23 |
24 | case val < 30:
25 | fmt.Println("is less than 30")
26 |
27 | default:
28 | fmt.Println("is greater than 30")
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/advanced/keywords/goto.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | // the goto keyword
7 | // for jumping to a labeled statement
8 |
9 | // how it work
10 |
11 | for i := 0; i <= 10; i++ {
12 | fmt.Println(i)
13 | if i == 5 {
14 | goto LOG
15 | // enter directly to the label
16 | }
17 | continue
18 | }
19 |
20 | LOG:
21 | fmt.Println("LOG label print")
22 | }
23 |
--------------------------------------------------------------------------------
/advanced/livelock/livelock.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "sync"
6 | "time"
7 | )
8 |
9 | /*
10 | Livelock:
11 |
12 | A livelock is like two friends trying to give
13 | each other a pen. Each friend has a pen and
14 | wants to give it to the other friend, but they
15 | both keep holding on to their own pen because
16 | they want the other person to give them their
17 | pen first. Neither of them can give their pen
18 | because they are both waiting for the other
19 | person to give their pen first. This is a l
20 | ivelock. In concurrent programming, livelocks
21 | happen when two or more tasks are unable to
22 | proceed because they are waiting for each other.
23 | Just like in the example, if the two friends had
24 | agreed to put their pens on a table and then pick
25 | up the pen they wanted, the livelock would be solved.
26 | */
27 |
28 | func main() {
29 | var lock1, lock2 sync.Mutex
30 |
31 | go func() {
32 | lock1.Lock()
33 | fmt.Println("goroutine 1 lock 1")
34 |
35 | time.Sleep(time.Second)
36 |
37 | lock2.Lock()
38 | fmt.Println("goroutine 1 lock 2")
39 |
40 | lock2.Unlock()
41 | lock1.Unlock()
42 | }()
43 |
44 | go func() {
45 | lock2.Lock()
46 | fmt.Println("goroutine 2 lock 2")
47 |
48 | time.Sleep(time.Second)
49 |
50 | lock1.Lock()
51 | fmt.Println("goroutine 2 lock 1")
52 |
53 | lock1.Unlock()
54 | lock2.Unlock()
55 | }()
56 |
57 | time.Sleep(time.Second * 10)
58 | }
59 |
--------------------------------------------------------------------------------
/advanced/new_vs_make/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | type Msg struct {
6 | Desc string
7 | From string
8 | }
9 |
10 | func main() {
11 | // The new built-in function allocates memory.
12 | // The first argument is a type, not a value,
13 | // and the value returned is a pointer to a newly
14 | // allocated zero value of that type.
15 |
16 | // new(Type)
17 | newMsg := new(Msg)
18 | fmt.Printf("%#v\n", newMsg)
19 | Change(newMsg)
20 | fmt.Printf("%#v\n", newMsg)
21 |
22 | // The make built-in function allocates and
23 | // initializes an object of type slice, map,
24 | // or chan (only). Like new, the first argument
25 | // is a type, not a value. Unlike new, make’s
26 | // return type is the same as the type of its
27 | // argument, not a pointer to it.
28 |
29 | // make(Type, Size)
30 | var makeSomthing = make([]string, 2)
31 | fmt.Printf("%#v\n", makeSomthing)
32 | }
33 |
34 | func Change(msg *Msg) {
35 | msg.Desc = "Changed description"
36 | }
37 |
--------------------------------------------------------------------------------
/advanced/strings/strings.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "strings"
6 | )
7 |
8 | func main() {
9 | // string are basic data structure, and every language has a number
10 | // of predefined functions for manipulating strings
11 | // in GO these are gathered in package `strings`
12 |
13 | myName := "Erfan"
14 |
15 | // HasPrefix function tests whether the string s begins with prefix
16 | fmt.Println(strings.HasPrefix(myName, "Erf"))
17 |
18 | // Contains function testing whether a string contain a substring
19 | fmt.Println(strings.Contains(myName, "f"))
20 |
21 | // Index and LastIndex functions
22 | fmt.Println(strings.Index(myName, "n"))
23 | fmt.Println(strings.LastIndex(myName, "v"))
24 |
25 | // Replacing string
26 | fmt.Println(strings.Replace(myName, "fan", "nan", 2))
27 |
28 | // Count function: return number of non-overlapping
29 | forTest := "Erfaaaaaaaaan"
30 | fmt.Println(strings.Count(forTest, "a"))
31 |
32 | // Repeat function
33 | fmt.Println(strings.Repeat("ba", 2))
34 |
35 | // Changing the case of the string
36 | fmt.Println(strings.ToLower(myName), strings.ToUpper(myName))
37 |
38 | // Trim functions
39 | withSpace := "Er fa n"
40 | trimLeftStr := "johnjohn"
41 | fmt.Println(strings.Trim(myName, "Er"))
42 | fmt.Println(strings.TrimSpace(withSpace))
43 | fmt.Println(strings.TrimLeft(trimLeftStr, "jo"))
44 | fmt.Println(strings.TrimRight(trimLeftStr, "hn"))
45 |
46 | // Splitting a string
47 | // - on whitespace
48 | fmt.Println(strings.Fields(myName))
49 |
50 | withWhiteSpace := "E r f an"
51 | fmt.Println(strings.Fields(withWhiteSpace))
52 |
53 | // - on a seprator
54 | fmt.Println(strings.Split(myName, ""))
55 |
56 | withSep := "E*rfa*n"
57 | fmt.Println(strings.Split(withSep, "*"))
58 |
59 | // Joining sliced string with Join method
60 | strSlice := strings.Split(myName, "")
61 | fmt.Println(strings.Join(strSlice, ""))
62 | }
63 |
--------------------------------------------------------------------------------
/advanced/sync_pkg/mutex.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "sync"
6 | )
7 |
8 | var i int
9 |
10 | func worker(wg *sync.WaitGroup, m *sync.Mutex) {
11 | m.Lock()
12 | i = i + 1
13 | m.Unlock()
14 |
15 | wg.Done()
16 | }
17 |
18 | func main() {
19 | // Sync package Mutex feature
20 |
21 | /*
22 | Mutex feature fixes the big issue called
23 | Race conditions(data racing).
24 |
25 | When two or more goroutines access the same
26 | memory location at least one of them is a write.
27 | */
28 |
29 | wg := new(sync.WaitGroup)
30 | m := new(sync.Mutex)
31 |
32 | for j := 0; j < 100; j++ {
33 | wg.Add(1)
34 | go worker(wg, m)
35 | }
36 |
37 | wg.Wait()
38 | fmt.Println(i)
39 | }
40 |
--------------------------------------------------------------------------------
/advanced/sync_pkg/waitGroup.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "sync"
6 | )
7 |
8 | func main() {
9 | // Sync package WaitGroup feature
10 |
11 | /*
12 | Golang Waitgroup allows you to block a
13 | specific code block to allow a set of
14 | goroutines to complete execution.
15 | An example would be to block the main
16 | function until the goroutines are completed
17 | and then unblocks the group.
18 | */
19 |
20 | wg := new(sync.WaitGroup)
21 |
22 | // Adds delta, which mey be negative, if the counter
23 | // become zero all go routines blocked on Wait are
24 | // released, if counter goes negative Add panics
25 | wg.Add(1)
26 |
27 | go printSomthing("from another go routine", wg)
28 |
29 | fmt.Println("from main go routine")
30 |
31 | // Wait blocks until the WaitGroup counter is zero
32 | wg.Wait()
33 | }
34 |
35 | func printSomthing(s string, wg *sync.WaitGroup) {
36 | // Done decrements the WaitGroup counter by one
37 | defer wg.Done()
38 |
39 | fmt.Println(s)
40 | }
41 |
--------------------------------------------------------------------------------
/resource/e-books/README.md:
--------------------------------------------------------------------------------
1 | ## E-books
2 |
3 | - [100 go mistakes: how to avoid them](https://www.manning.com/books/100-go-mistakes-and-how-to-avoid-them)
4 | - [A go developer's notebook](https://leanpub.com/GoNotebook/read)
5 | - [An introduction to programming in go](https://www.golang-book.com/)
6 | - [Build an orchestrator in go](https://www.manning.com/books/build-an-orchestrator-in-go)
7 | - [Build web application with golang](https://astaxie.gitbooks.io/build-web-application-with-golang/content/en/)
8 | - [Build web apps with go](https://codegangsta.gitbooks.io/building-web-apps-with-go/content/)
9 | - [For the love of go](https://bitfieldconsulting.com/books/love)
10 | - [Go 101](https://go101.org/)
11 | - [Go bootcamp](http://golangbootcamp.com/)
12 | - [Go succinctly](https://github.com/thedevsir/gosuccinctly)
13 | - [Go books](https://github.com/dariubs/GoBooks)
14 | - [Learning go](https://www.miek.nl/downloads/Go/Learning-Go-latest.pdf)
15 | - [Network programming with go](https://jan.newmarch.name/go/)
16 | - [Practical go leason](https://www.practical-go-lessons.com/)
17 | - [The go programming language](https://www.gopl.io/)
18 | - [Writing a compiler in go](https://compilerbook.com/)
19 |
--------------------------------------------------------------------------------
/resource/web-sites/README.md:
--------------------------------------------------------------------------------
1 | ## web-sites
2 |
3 | - [The official go blog](https://go.dev/blog/)
4 | - [A hub for go developers](https://go.dev)
5 | - [Golang developers job](https://golangjob.xyz)
6 | - [Golang resources](https://golangresources.com)
7 | - [Learning go programming](https://blog.learngoprogramming.com)
8 | - [Learn go](https://golangr.com)
9 | - [Go by example](https://gobyexample.com)
10 | - [Go basic syntax](https://www.tutorialspoint.com/go/go_basic_syntax.htm)
11 |
--------------------------------------------------------------------------------
/testing/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/erfidev/go-document/testing
2 |
3 | go 1.16
4 |
--------------------------------------------------------------------------------
/testing/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | type Person struct {
6 | name string
7 | age int
8 | }
9 |
10 | func main() {
11 | // writing tests in go programming language
12 | // Go's built-in support for unit testing makes
13 | // it easier to test as you go
14 |
15 | erfan, err := NewPerson("erfan", 17)
16 | if err != nil {
17 | fmt.Println(err)
18 | return
19 | }
20 |
21 | fmt.Println(erfan)
22 | }
23 |
24 | func NewPerson(name string, age int) (Person, error) {
25 | return Person{
26 | name, age,
27 | }, nil
28 | }
29 |
--------------------------------------------------------------------------------
/testing/main_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "testing"
4 |
5 | // Now that you've gotten your code to a stable place
6 | // (nicely done, by the way), add a test. Testing your
7 | // code during development can expose bugs that find
8 | // their way in as you make changes
9 |
10 | func TestMain(t *testing.T) {
11 | _, err := NewPerson("test", 1)
12 |
13 | if err != nil {
14 | t.Error("test failed!")
15 | }
16 | // for run tests we should write
17 | // go test . =>> or =>> go test -v or =>> go test
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/web-server/1 - hello-world/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "net/http"
4 |
5 | // Basic Example of web servers
6 | func main() {
7 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
8 | w.Write([]byte("Hello, world!"))
9 | })
10 |
11 | http.ListenAndServe(":3000", nil)
12 | }
13 |
--------------------------------------------------------------------------------
/web-server/2 - routing/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "net/http"
4 |
5 | func main() {
6 | Router := http.NewServeMux()
7 |
8 | Router.HandleFunc("/", Home)
9 | Router.HandleFunc("/about", About)
10 |
11 | server := http.Server{
12 | Addr: ":3000",
13 | Handler: Router,
14 | }
15 |
16 | server.ListenAndServe()
17 | }
18 |
19 | func Home(w http.ResponseWriter, r *http.Request) {
20 | w.Write([]byte("`/` Route"))
21 | }
22 |
23 | func About(w http.ResponseWriter, r *http.Request) {
24 | w.Write([]byte("`/about` Route"))
25 | }
26 |
--------------------------------------------------------------------------------
/web-server/3 - middleware/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | )
7 |
8 | func main() {
9 | Router := http.NewServeMux()
10 |
11 | Router.HandleFunc("/", Home)
12 | // Router → Middleware Handler → Application Handler
13 | Router.Handle("/about", Middleware(About))
14 |
15 | server := http.Server{
16 | Addr: ":3000",
17 | Handler: Router,
18 | }
19 |
20 | server.ListenAndServe()
21 | }
22 |
23 | func Home(w http.ResponseWriter, r *http.Request) {
24 | w.Write([]byte("`/` Route"))
25 | }
26 |
27 | func Middleware(next http.HandlerFunc) http.Handler {
28 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
29 | fmt.Println("middleware mission success")
30 | next.ServeHTTP(w, r)
31 | })
32 | }
33 |
34 | func About(w http.ResponseWriter, r *http.Request) {
35 | w.Write([]byte("`/about` Route with middleware"))
36 | }
37 |
--------------------------------------------------------------------------------
/web-server/4 - static-directory/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "net/http"
4 |
5 | func main() {
6 | fileServer := http.FileServer(http.Dir("./static"))
7 |
8 | http.Handle("/", fileServer)
9 | // If we start the program and going on "/index.html" path
10 | // we see the index.html page on the static folder
11 | // that is easy!
12 |
13 | http.ListenAndServe(":3000", nil)
14 | }
15 |
--------------------------------------------------------------------------------
/web-server/4 - static-directory/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |