Skip to content

Commit

Permalink
Refactor code to remove unnecessary package and unused imports
Browse files Browse the repository at this point in the history
  • Loading branch information
Pradumnasaraf committed Sep 13, 2024
1 parent c0d5f72 commit 61b80de
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 69 deletions.
1 change: 0 additions & 1 deletion docs/golang/concepts/11) slices.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ func main() {
var fruits []string // We don't need to specify the size of the array
// fruits := []string{} - We can also use this syntax to create a slice
// fruits := make([]string, 2) - We can also use make function to create a slice

fruits = append(fruits, "Apple")
fruits = append(fruits, "Orange")
fruits = append(fruits, "Banana")
Expand Down
7 changes: 4 additions & 3 deletions docs/golang/concepts/32) channels.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import (
)

func main() {
myChannel := make(chan int, 2) // buffered channel. By default, it is unbuffered

myChannel := make(chan int, 2) // buffered channel
// var myChannel chan int // unbuffered channel
wg := &sync.WaitGroup{}


wg.Add(2)
go func(ch chan int, wg *sync.WaitGroup) {
fmt.Println(<-ch) // read from channel


wg.Done()
}(myChannel, wg)

Expand Down
37 changes: 21 additions & 16 deletions docs/golang/concepts/33) channels-open.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,30 @@ import (
)

func main() {
// When channel is closed, the value read from the channel is the zero value and at the same time maybe the write value can also be zero value.
// So we need to check if the channel is closed or not by using the second return value of the read operation.

myChannel := make(chan int, 2)
wg := &sync.WaitGroup{}
myCh := make(chan int, 1)

wg.Add(2)
go func(ch <-chan int, wg *sync.WaitGroup) {
val, isChannelOpen := <-ch
fmt.Println(val, isChannelOpen)
wg.Done()
}(myChannel, wg)

go func(ch chan<- int, wg *sync.WaitGroup) {
// ch <- 5 uncomment this line to see the difference
close(myChannel)
wg.Done()

}(myChannel, wg)

go func(channel chan int, wait *sync.WaitGroup) {
fmt.Println("First Go Routine")
wait.Done()

value, isChannelOpen := <-myCh

if !isChannelOpen {
fmt.Println("Channel Closed")
}
fmt.Println(value)
}(myCh, wg)

go func(channel chan int, wait *sync.WaitGroup) {
fmt.Println("Second Go Routine")
// myCh <- 3
close(myCh)
wait.Done()
// myCh <- 5
}(myCh, wg)

wg.Wait()
}
43 changes: 20 additions & 23 deletions docs/golang/concepts/34) Interface.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,36 @@
package main

import "fmt"
import (
"fmt"
"math"
)

type Printer interface {
printInfo()
type shape interface {
area() float64
}


type Book struct {
Title string
Price float32
type circle struct {
radius float64
}

type Drink struct {
Name string
Price float32
type rectangle struct {
width float64
length float64
}

func (b Book) printInfo() {
fmt.Println("Book Title:", b.Title, "Price:", b.Price)
func (r rectangle) area() float64 {
return r.length * r.width
}

func (d Drink) printInfo() {
fmt.Println("Drink Name:", d.Name, "Price:", d.Price)
func (c circle) area() float64 {
return 2 * math.Pi * c.radius
}

func main() {
book := Book{Title: "The Alchemist", Price: 9.99}
drink := Drink{Name: "Coke", Price: 1.99}

// book.printInfo()
// drink.printInfo()
myRectangle := rectangle{width: 8, length: 10}
fmt.Println(myRectangle.area())

info := []Printer{book, drink}
myCircle := circle{radius: 10}
fmt.Println(myCircle.area())

info[0].printInfo()
info[1].printInfo()

}
158 changes: 132 additions & 26 deletions docs/golang/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,10 @@ func (t Test) printName() {
}
```

## Methods

Methods are functions that are associated with a type. They are similar to functions but are defined with a receiver. The receiver is like a parameter. It is the first argument of the method.

```go
type Person struct {
name string
Expand Down Expand Up @@ -546,19 +550,34 @@ The purpose of a goroutine is to run a function concurrently with other function

```go
func main() {
go greeter("First Statement")
go greeter("Second Statement")
greeter("Third Statement")
p := Person{Name: "John", Age: 25}

data, err := json.Marshal(p)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(data))

var p1 Person
err = json.Unmarshal(data, &p1)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(p1)
}
```

func greeter(s string) {

for i := 0; i < 5; i++ {
time.Sleep(1 * time.Second)
fmt.Println(s)
}
}
## Go routines and WaitGroup

- A goroutine is a lightweight thread managed by the Go runtime. We can create a goroutine using the keyword `go`. It is similar to threads in other languages. The purpose of a goroutine is to run a function concurrently with other functions.

```go
go func() {
fmt.Println("Hello")
}()
```

- If the main function exits, the program will exit immediately even if the goroutine is still running. To prevent this, we can use the `WaitGroup` type. For Eg:
Expand Down Expand Up @@ -623,38 +642,115 @@ type Person struct {

- `make()` - It is used to create a channel. It takes the type of the channel as an argument.

```go
ch := make(chan int)

go func() {
ch <- 10
}()

val := <-ch
fmt.Println(val)
```

We can create a buffered channel by passing the buffer size as the second argument to the `make()` function. By default, the channel is unbuffered and can only hold one value. So, if we try to send multiple value to the channel it will give an error.


### Buffered Channel

A buffered channel is a channel with a buffer. It can hold multiple values. We can specify the buffer size when we create the channel.

```go
var ch = make(chan int, 5) // buffered channel with a buffer size of 5
```

### Unbuffered Channel

An unbuffered channel is a channel without a buffer. It can hold only one value. We can send a value to the channel only if there is a goroutine ready to receive the value.

```go
var ch = make(chan int) // unbuffered channel
```

var ch = make(chan int, 10) // buffered channel
### Closing a Channel

We can close a channel using the `close()` function. It is used to indicate that no more values will be sent on the channel.

```go
msg := make(chan int)

go func() {
msg <- 1
close(msg) // After closing the channel we can't send any more values
}()
```

But here a catch even tho channel is closed we can still receive the values from it like zero, so it's dalmatic whether the it's channel is closed or the value is zero. To overcome this we can receive the value and a boolean value which will tell us whether the channel is closed or not.

```go
ch := make(chan int)
package main

ch <- 10 // It will send 10 to the channel
import (
"fmt"
"sync"
)

<- ch // It will receive from the channel
val, ok := <- ch // It will receive from the channel and check if the channel is closed or not
```
var wait = sync.WaitGroup{}

- `close()` - It is used to close a channel. It takes the channel as an argument.
func main() {

myChannel := make(chan int, 1)

wait.Add(2)
go func() {
fmt.Println("First Go Routine")
wait.Done()

hello, isChannelOpen := <- myChannel

if !isChannelOpen {
fmt.Println("Channel Closed")
}
fmt.Println(hello)
}()

go func() {
fmt.Println("Second Go Routine")
close(myChannel)
wait.Done()
// myChannel <- 5
}()

wait.Wait()
}
```


#### Send Only Channel
### Send Only Channel

```go
var ch = make(chan<- int) // send only channel
```

Receive Only Channel
```go
go func (ch chan<- int) {
ch <- 10
}(ch)
```

### Receive Only Channel

```go
var ch = make(<-chan int) // receive only channel
```

```go
go func (ch <-chan int) {
val := <-ch
fmt.Println(val)
}(ch)
```

### IIF's (Immediately Invoked Functions)

- An immediately invoked function is a function that is executed as soon as it is created. It is a function that is executed immediately after it is created. It is also known as a self-invoking function.
Expand All @@ -665,19 +761,29 @@ func main() {
fmt.Println("Hello")
}()
}
``` -->
```
## Error Handling

<!-- ### Race Conditions
In Go, errors are values. We can use the `error` type to represent an error. We can use the `errors.New` function to create a new error. It returns an error.

Race Conditions occur when two or more goroutines access the same variable concurrently and at least one of the accesses is a write. It can lead to unpredictable results.
```go
func divide(x, y int) (int, error) {
if y == 0 {
return 0, errors.New("division by zero")
}
return x / y, nil
}
```

We can check whether there is a race condition in our code by using the `-race` flag.
### Code Organization

```bash
go run --race main.go
```
We can organize our code by putting functions/ variables in different files and can use them in the main file or calling the main function from other files.

Also, we can have multiple packages in a single directory.

To avoid the race condition we can use the `sync` package. We can use the `Mutex` type to lock the variable.
### Expoting and Importing

- We can export a function/ variable by capitalizing the first letter of the function/ variable name. Now we can use it in other packages.

```go
var mutex sync.Mutex
Expand Down

0 comments on commit 61b80de

Please sign in to comment.