Skip to content

joosejunsheng/golang-notes

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 

Repository files navigation

golang-notes

Channels

func main(){
    ch1 := make(chan int)
    go func(){
        for i := 0; i < 10; i++ {
            ch1 <- i
        }
    }()
    for n := range ch1 {
        fmt.Printf("n = %d\n", n)
    }
}

range behaves differently with slice and with channel.

When it comes to slice, range actually runs only once to iterate the entire slice once.

But when it comes to channel, range behaves in a way that it continues to loop to wait for and receive values from channel UNTIL channel is closed.

In the case above, the code will result in fatal error: all goroutines are asleep - deadlock!

To fix it, just add a close after iterating the loop in the goroutine

func main(){
    ch1 := make(chan int)
    go func(){
        for i := 0; i < 10; i++ {
            ch1 <- i
        }
	close(ch1) // <------ This line to fix close the channel
    }()
    for n := range ch1 {
        fmt.Printf("n = %d\n", n)
    }
}

Result :

n = 0
n = 1
n = 2
n = 3
n = 4
n = 5
n = 6
n = 7
n = 8
n = 9

select

Using select in Go is like listening for available data on channel, or even multiple channels!

One Channel

func sendData(ch chan string, message string, delay time.Duration) {
    time.Sleep(delay)
    ch <- message
}

func main() {
    ch1 := make(chan string)

    go sendData(ch1, "Message from Channel 1", 3*time.Second)

    for {
        select {
        case msg := <-ch1:
            fmt.Println("Received from Channel 1:", msg)
        default:
            fmt.Println("INFINITE LOOP")
        }
    }
}

The for loop above will be an infinite loop to select, repeating to consume data whenever data is ready in channels

Result :

INFINITE LOOP
INFINITE LOOP
INFINITE LOOP
INFINITE LOOP
INFINITE LOOP
INFINITE LOOP
...
Received from Channel 1: Message from Channel 1 <----- After 3 seconds
INFINITE LOOP
INFINITE LOOP
INFINITE LOOP
INFINITE LOOP
...

Multiple Channels

func sendData(ch chan string, message string, delay time.Duration) {
    time.Sleep(delay)
    ch <- message
}

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)

    go sendData(ch1, "Message from Channel 1", 3*time.Second)
    go sendData(ch2, "Message from Channel 2", 1*time.Second)

    for {
        select {
        case msg := <-ch1:
            fmt.Println("Received from Channel 1:", msg)
        case msg := <-ch2:
            fmt.Println("Received from Channel 2:", msg)
        default:
            fmt.Println("INFINITE LOOP")
        }
    }
}

Result :

INFINITE LOOP
INFINITE LOOP
INFINITE LOOP
...
Received from Channel 2: Message from Channel 2 <----- After 1 seconds
...
INFINITE LOOP
INFINITE LOOP
INFINITE LOOP
...
Received from Channel 1: Message from Channel 1 <----- After 3 seconds
INFINITE LOOP
INFINITE LOOP
INFINITE LOOP
INFINITE LOOP
...

Efficiently Resizing Slice

a := []int{1, 2, 3, 4, 5}
numFree := len(a)
fmt.Println(a) // Output: [1 2 3 4 5]

copy(a, a[1:])
fmt.Println(a) // Output: [2 3 4 5 5]

res = a[:numFree-1]
fmt.Println(res) // Output: [2 3 4 5]

Using a = a[1:] will end up printing the same output as res = a[:numFree-] but why the write more codes?

Technically when you re-assign a slice, eg. b = a[1:], res = a[:numFree-], it creates a new slice by pointing to the original slice / shares the same underlying array. The memory is still allocated even if you do b = a[1:], the only difference is the new slice b = a[1:] is an entire new slice referencing the original slice where it starts from the position 1 instead of 0, a[0] is still in the memory.

By using copy(a, a[1:]), it moves the entire slice 1 position to the left. res = a[:numFree-1] is then executed to shorten the slice by 1, end up with a size of 4, remaining the capacity of 5. This will not leave a[0] "dangling" in the background like what we did using a = a[1:].

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published