0
package main

import (
    "fmt"
    "sync"
)

// PUT function
func put(hashMap map[string](chan int), key string, value int, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Printf("this is getting printed")
    hashMap[key] <- value
    fmt.Printf("this is not getting printed")
    fmt.Printf("PUT sent %d\n", value)
}

func main() {
    var value int
    var key string
    wg := &sync.WaitGroup{}
    hashMap := make(map[string](chan int), 100)
    key = "xyz"
    value = 100
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go put(hashMap, key, value, wg)
    }
    wg.Wait()
}

The last two print statements in the put function are not getting printed, I am trying to put values into the map based on key.

and also how to close the hashMap in this case.

wasmup
  • 14,541
  • 6
  • 42
  • 58
charanReddy
  • 137
  • 1
  • 11
  • 2
    See possible duplicate [No output from goroutine](https://stackoverflow.com/questions/28958192/no-output-from-goroutine/28958240#28958240), otherwise provide a [mcve]. – icza Mar 12 '20 at 04:04
  • 5
    You do initialize channels in the map right? Else indexing the map you get a `nil` channel, and sending on a `nil` channel blocks forever, see [How does a non initialized channel behave?](https://stackoverflow.com/questions/39015602/how-does-a-non-initialized-channel-behave/39016004#39016004) – icza Mar 12 '20 at 04:07
  • How do you initialize the map in the above case? I have added the reproducible code – charanReddy Mar 12 '20 at 04:29

3 Answers3

4
  1. You need to create a channel, for example hashMap[key] = make(chan int)
  2. Since you are not reading from the channel, you need buffered channel to make it work:
    key := "xyz"
    hashMap[key] = make(chan int, 5)

Try the following code:

func put(hashMap map[string](chan int), key string, value int, wg *sync.WaitGroup) {
    hashMap[key] <- value
    fmt.Printf("PUT sent %d\n", value)
    wg.Done()
}
func main() {
    var wg sync.WaitGroup
    hashMap := map[string]chan int{}
    key := "xyz"
    hashMap[key] = make(chan int, 5)
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go put(hashMap, key, 100, &wg)
    }
    wg.Wait()
}

Output:

PUT sent 100
PUT sent 100
PUT sent 100
PUT sent 100
PUT sent 100
wasmup
  • 14,541
  • 6
  • 42
  • 58
  • In my case, keys might change...soo statement 1 doesn't make sense there.....I want a hashmap of 100 values where I can write(key, value) and read(key) from it – charanReddy Mar 12 '20 at 04:55
  • is this hashMap := make(chan map[string](int), 100) more appropriate in my case? – charanReddy Mar 12 '20 at 04:56
  • but doesn't that mean buffer of 5 values for hashMap[key]?? I need a hashMap of 100 (i.e., (key1, value1)....(key100, value100)) – charanReddy Mar 12 '20 at 05:00
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/209498/discussion-between-charanreddy-and-wasmup). – charanReddy Mar 12 '20 at 05:10
0

My solution to fix the problem is:

// PUT function
func put(hashMap map[string](chan int), key string, value int, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Printf("this is getting printed")
    hashMap[key] <- value // <-- nil problem
    fmt.Printf("this is not getting printed")
    fmt.Printf("PUT sent %d\n", value)
}

in this line of code hashMap[key] <- value in put function, It cannot accept the value because chan int is nil which is define in put (hashMap map[string](chan int) parameter.

// PUT function
func put(hashMap map[string](chan int), cval chan int, key string, value int, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Println("this is getting printed")
    cval <- value // put the value in chan int (cval) which is initialized
    hashMap[key] = cval // set the cval(chan int) to hashMap with key
    fmt.Println("this is not getting printed")
    fmt.Printf("PUT sent %s %d\n", key, value)
}

func main() {
    var value int
    wg := &sync.WaitGroup{}

    cval := make(chan int,100)
    hashMap := make(map[string](chan int), 100)

    value = 100
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go put(hashMap, cval, fmt.Sprintf("key%d",i), value, wg)
    }
    wg.Wait()

    /* uncomment to test cval 
    close(cval)

    fmt.Println("Result:",<-hashMap["key2"])
    fmt.Println("Result:",<-hashMap["key1"])
    cval <- 88 // cannot send value to a close channel
    hashMap["key34"] = cval
    fmt.Println("Result:",<-hashMap["key1"])
    */


}

In my code example. I initialized cval buffered channel 100 same size to hashMap and pass cval as value in put function. you can close cval only and not the hashMap itself.

Adriel Artiza
  • 327
  • 4
  • 12
-1

Also, your code can be reduced to this. Why pass params unnecessarily! One extra modification is that I take different values to make you understand the concept clearer.

package main

import (
    "log"
    "sync"
)

func put(hash chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    log.Println("Put sent: ", <-hash)
}

func main() {
    hashMap := map[string]chan int{}
    key := "xyz"
    var wg sync.WaitGroup
    hashMap[key] = make(chan int, 5)
    for i := 0; i < 5; i++ {
        value := i
        wg.Add(1)
        go func(val int) {
            hashMap[key] <- val
            put(hashMap[key], &wg)
        }(value)
    }
    wg.Wait()
}
shmsr
  • 3,802
  • 2
  • 18
  • 29