├── .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 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | Boom that is easy! 11 | 12 | 13 | -------------------------------------------------------------------------------- /web-server/5 - templates/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "html/template" 5 | "net/http" 6 | ) 7 | 8 | func main() { 9 | // Initializing template 10 | tmp, _ := template.ParseFiles("./templates/home.gohtml") 11 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 12 | // Executing template 13 | tmp.Execute(w, map[string]string{ 14 | "title": "home page title", 15 | }) 16 | }) 17 | 18 | http.ListenAndServe(":3000", nil) 19 | } 20 | -------------------------------------------------------------------------------- /web-server/5 - templates/templates/home.gohtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{.title}} 4 | 5 | 6 | Home page...with using templates 7 | 8 | -------------------------------------------------------------------------------- /web-server/6 - tls-protocol/request.http: -------------------------------------------------------------------------------- 1 | GET https://localhost:5000 -------------------------------------------------------------------------------- /web-server/6 - tls-protocol/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "log" 6 | "net/http" 7 | ) 8 | 9 | func main() { 10 | srv := NewServer() 11 | // install openssl library 12 | // run the command `openssl genrsa -out server.key 2048` in the root of your app 13 | // then run this command `openssl ecparam -genkey -name secp384r1 -out server.key` 14 | /* 15 | if the server return warning 16 | called bad tls handshake error 17 | don't worry about that 18 | becuase this tls we generated in localy 19 | and browser check global tls keys 20 | and return the warning 21 | */ 22 | err := srv.ListenAndServeTLS("server.crt", "server.key") 23 | log.Println("Server run on 5000 port") 24 | if err != nil { 25 | log.Fatalf("we have error when running server: %v", err) 26 | } 27 | } 28 | 29 | func NewServer() http.Server { 30 | router := http.NewServeMux() 31 | 32 | router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 33 | w.Write([]byte("Goood!")) 34 | }) 35 | 36 | tlsConfig := &tls.Config{ 37 | PreferServerCipherSuites: true, 38 | CurvePreferences: []tls.CurveID{ 39 | tls.CurveP256, 40 | tls.X25519, 41 | }, 42 | MinVersion: tls.VersionTLS12, 43 | CipherSuites: []uint16{ 44 | tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 45 | tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 46 | tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 47 | tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 48 | tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 49 | tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 50 | }, 51 | } 52 | 53 | server := http.Server{ 54 | Addr: ":5000", 55 | Handler: router, 56 | TLSConfig: tlsConfig, 57 | } 58 | 59 | return server 60 | } 61 | -------------------------------------------------------------------------------- /web-server/README.md: -------------------------------------------------------------------------------- 1 | # Web Server 2 | 3 | - hello-world 4 | - routing 5 | - middleware 6 | - static directory routing 7 | - templates 8 | --------------------------------------------------------------------------------