Unexpected output when printing time.Time [duplicate] - go

This question already has answers here:
What is the "m" in timestamp and how to get timestamp without "m"?
(3 answers)
Closed 3 years ago.
"I'm trying to output the values of a channel , which received values from a struct, which should be a string and time. It outputs those two, but then it includes this strange line " +0300 +03 m=+0.001997101" after the time."
Tried many other things from fmt package, but still no help. Tried things from the time package too
package main
import (
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"time"
)
var wg sync.WaitGroup
type widget struct {
Label string
Time time.Time
}
func main() {
c := make(chan widget)
sc := make(chan os.Signal, 1)
done := make(chan bool, 1)
signal.Notify(sc, syscall.SIGINT,
syscall.SIGTERM,
syscall.SIGHUP,
syscall.SIGKILL,
syscall.SIGSEGV,
)
go func() {
sig := <-sc
fmt.Println()
fmt.Println(sig)
done <- true
}()
go send(c)
go receive(c)
<-done
fmt.Println("Program exited")
}
func send(p chan<- widget) {
producer := widget{
"widget_id_34",
time.Now(),
}
p <- producer
}
//where im grtting the problem from i beilieve
func receive(c <-chan widget) {
out := <-c
fmt.Printf("%v", out)
//fmt.Fprintln(os.Stdout, <-c)
}

The m field is the monotonic time. Per the docs:
The canonical way to strip a monotonic clock reading is to use t = t.Round(0).
Doing so yields a time without a m value. The +0300 is the time zone offset, which is part of the time value (without it, the time value would be useless, because it would have a margin of error of +/- 23 hours).

Related

Golang: how to send signal and stop sending values to a goroutine

I am new to go and I am trying to learn some basic use of signal functions in goroutines. I have an infinite for loop in go. Through this for loop, I pass values to a goroutine through a channel. I also have a threshold value after which I will like to stop sending values indefinitely to the goroutine (i.e. close the channel). When the threshold value is reached, I will like to break the for loop. Following is what I have tried so far.
In this particular example, thresholdValue = 10 and I would like to print values from 0 , ..., 9 and then stop.
I followed this post on medium and this post on stackoverflow. I picked elements from these posts which I could use.
This is what I have done at the present. In the main function of my code, I purposefully make the for loop an infinite loop. My main intention is to learn how to have the goroutine readValues() take the threshold value and then stop transmission of values indefinitely in the channel.
package main
import (
"fmt"
)
func main() {
ch := make(chan int)
quitCh := make(chan struct{}) // signal channel
thresholdValue := 10 //I want to stop the incoming data to readValues() after this value
go readValues(ch, quitCh, thresholdValue)
for i:=0; ; i++{
ch <- i
}
}
func readValues(ch chan int, quitCh chan struct{}, thresholdValue int) {
for value := range ch {
fmt.Println(value)
if (value == thresholdValue){
close(quitCh)
}
}
}
The goroutine in my code still misses the threshold. I will appreciate any direction as to how I should proceed from here.
to show good faith, this is the program rewritten.
package main
import (
"log"
"sync"
"time"
)
func main() {
ch := make(chan int, 5) // capacity increased for demonstration
thresholdValue := 10
var wg sync.WaitGroup
wg.Add(1)
go func() {
readValues(ch)
wg.Done()
}()
for i := 0; i < thresholdValue; i++ {
ch <- i
}
close(ch)
log.Println("sending done.")
wg.Wait()
}
func readValues(ch chan int) {
for value := range ch {
<-time.After(time.Second) // for demonstratin purposes.
log.Println(value)
}
}
In this version readValues exits because the for loop did exit and that main closed ch.
In other words a stop condition take effects and triggers the exit sequence (signal end of input then wait for the processing to finish)

Listen one channel on multiple places in Go [duplicate]

This question already has answers here:
How to broadcast message using channel
(7 answers)
Closed 3 years ago.
I know if once get the data from a channel that data won't receive from any other place that channel is waiting. However, if I want to design a program broadcast that channel has got data and It is ready to take out in different places without affecting other channels but in all places, I need to receive data in the same order, what will be the best design?
As a example:
func sender(c chan int){
c-> 5
}
func reciever1(c chan int){
i:= <-c
...
}
func reciever2(c chan int){
i:= <-c
...
}
Here when executing both reciever1() and reciver2() Both should get same result.
You have to create multiple channels and pass the same value to each of those channels.
Example
package main
import (
"fmt"
)
func main(){
chann1 := make(chan int)
chann2 := make(chan int)
go func(){
for {
val :=<- chann1
fmt.Println("GORoutine 1", val)
}
}()
go func(){
for {
val :=<- chann2
fmt.Println("GORoutine 2", val)
}
}()
for i:=0;i<=10;i++{
chann1 <- i
chann2 <- i
}
}

bounded parallelism to hash strings [duplicate]

This question already has answers here:
How would you define a pool of goroutines to be executed at once?
(5 answers)
Closed 4 years ago.
Trying to solve the problem of reading phone numbers from a file (line by line) and hash them concurrently (md5) in go with a maximum of 100 concurrent process maximum, creating a fixed number of goroutines. tried using go pipeline and bounded parallelism but did not work. any guidance, please?
this is what I tried, https://play.golang.org/p/vp7s512l8w4
package main
import (
"bufio"
"fmt"
"os"
"sync"
)
func hashPhoneNumers(phoneNO string, ch chan struct{}, group *sync.WaitGroup) {
do_hash(phoneNO)
<-ch
group.Done()
}
func do_hash(s string) {
fmt.Println("do hash: ", s)
}
func main() {
c := make(chan struct{}, 100)
file, err := os.Open("file.txt")
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
defer file.Close()
line := bufio.NewScanner(file)
wg := sync.WaitGroup{}
for line.Scan() {
// with a maximum of 100 concurrent process maximum
c <- struct{}{}
wg.Add(1)
go hashPhoneNumers(line.Text(), c, &wg)
}
// wait all goroutines done
wg.Wait()
close(c)
}
this works fine

Golang deadlock that I resolved by luck, need explanation

I'm trying to understand go channel and go routine. To do so, I'm doing online exercises. I found one here: http://whipperstacker.com/2015/10/05/3-trivial-concurrency-exercises-for-the-confused-newbie-gopher/
I resolved the 3rd one (named "Internet cafe").
But there's something I resolved by "luck", and it's bother me because I don't understand my issue and why my "hack" fixed it.
In my code below, I replace "enterChan <- next" by "go func() { enterChan <- next }()", and it solved my deadlock.
Can someone explain to me why it deadlock before, and why it works with this hack ? Is it a proper solution, or an ugly one ?
Don't hesitate to criticize my code, I'm searching to improve :)
Many thanks!
This is my code:
package main
import (
"fmt"
"math/rand"
"strconv"
"time"
)
const (
maxNumberOfUser = 8
)
func useComputer(tourist string, leaverChan chan string) {
seed := rand.NewSource(time.Now().UnixNano())
random := rand.New(seed)
fmt.Println(tourist, "is online")
d := random.Intn(120-15) + 15
time.Sleep(time.Duration(d) * time.Millisecond * 10)
fmt.Println(tourist, "is done, having spent", d, "minutes online.")
leaverChan <- tourist
}
func manageUsers(enterChan, leaverChan chan string, stopChan chan struct{}) {
nbUsed := 0
queue := make([]string, 0)
for {
select {
case tourist := <-enterChan:
if nbUsed < maxNumberOfUser {
nbUsed++
go useComputer(tourist, leaverChan)
} else {
fmt.Println(tourist, "waiting for turn.")
queue = append(queue, tourist)
}
case tourist := <-leaverChan:
nbUsed--
fmt.Println(tourist, "is leaving, number of free place is now:", maxNumberOfUser-nbUsed)
if len(queue) > 0 {
next := queue[0]
queue = queue[1:]
go func() {
enterChan <- next
}()
} else if nbUsed == 0 {
close(stopChan)
return
}
}
}
}
func main() {
enterChan := make(chan string)
leaverChan := make(chan string)
stopChan := make(chan struct{})
go manageUsers(enterChan, leaverChan, stopChan)
for i := 1; i <= 25; i++ {
enterChan <- "Tourist " + strconv.Itoa(i)
}
<-stopChan
fmt.Println("The place is empty, let's close up and go to the beach!")
}
As explained by #dev.bmax, enterChan is not a buffered channel and you are trying to send data to a channel that is not being read. For example, below code results in a deadlock error:
package main
import (
"fmt"
)
func main() {
stream := make(chan int)
<-stream
stream<-1
fmt.Println("Yayyy!! no deadlock!")
}
you can run the above code here and check that it has deadlock. But if I change it to this:
package main
import (
"fmt"
)
func main() {
stream := make(chan int)
go func(){<-stream}()
stream<-1
fmt.Println("Yayyy!! no deadlock!")
}
we have no deadlock. Because we started another GoRoutine which is reading from the channel while the main GoRoutine is pushing data to channel. Hope this helps!

go concurrency all goroutines are asleep - deadlock

Sorry about the noob question but I'm having a hard time wrapping my head around the concurrency part of go. Basically this program below is a simplified version of a larger one I'm writing, thus I want to keep the structure similar to below.
Basically instead of waiting 4 seconds I want to run addCount(..) concurrent using the unbuffered channel and when all elements in the int_slice has been processed I want to do another operation on them. However this program ends with a "panic: close of closed channel" and if I remove the closing of the channel I'm getting the output I'm expecting but it panics with: "fatal error: all goroutines are asleep - deadlock"
How can I implement the concurrency part correctly in this scenario?
Thanks in advance!
package main
import (
"fmt"
"time"
)
func addCount(num int, counter chan<- int) {
time.Sleep(time.Second * 2)
counter <- num * 2
}
func main() {
counter := make(chan int)
int_slice := []int{2, 4}
for _, item := range int_slice {
go addCount(item, counter)
close(counter)
}
for item := range counter {
fmt.Println(item)
}
}
Here are the issues I spotted in the code, and below a working version based on your implementation.
If a goroutine tries to write to an "unbuffered" channel, it will block until someone reads from it. Since you are not reading until they finish writing to the channel, you have a deadlock there.
Closing the channel while they are blocked breaks the deadlock, but gives an error since they now can't write to a closed channel.
Solution involves:
Creating a buffered channel so that they can write without blocking.
Using a sync.WaitGroup so that you wait for the goroutines to finish before closing the channel.
Reading from the channel at the end, when all is done.
See here, with comments:
package main
import (
"fmt"
"time"
"sync"
)
func addCount(num int, counter chan<- int, wg *sync.WaitGroup) {
// clear one from the sync group
defer wg.Done()
time.Sleep(time.Second * 2)
counter <- num * 2
}
func main() {
int_slice := []int{2, 4}
// make the slice buffered using the slice size, so that they can write without blocking
counter := make(chan int, len(int_slice))
var wg sync.WaitGroup
for _, item := range int_slice {
// add one to the sync group, to mark we should wait for one more
wg.Add(1)
go addCount(item, counter, &wg)
}
// wait for all goroutines to end
wg.Wait()
// close the channel so that we not longer expect writes to it
close(counter)
// read remaining values in the channel
for item := range counter {
fmt.Println(item)
}
}
For the sake of having examples here's a slightly modified version of what #eugenioy submitted. It allows for the use of an unbuffered channel and the reading of values as they come in instead of at the end like a regular for loop.
package main
import (
"fmt"
"sync"
"time"
)
func addCount(num int, counter chan<- int, wg *sync.WaitGroup) {
// clear one from the sync group
defer wg.Done()
// not needed, unless you wanted to slow down the output
time.Sleep(time.Second * 2)
counter <- num * 2
}
func main() {
// variable names don't have underscores in Go
intSlice := []int{2, 4}
counter := make(chan int)
var wg sync.WaitGroup
for _, item := range intSlice {
// add one to the sync group, to mark we should wait for one more
wg.Add(1)
go addCount(item, counter, &wg)
}
// by wrapping wait and close in a go routine I can start reading the channel before its done, I also don't need to know the size of the
// slice
go func() {
wg.Wait()
close(counter)
}()
for item := range counter {
fmt.Println(item)
}
}
package main
import (
"fmt"
"time"
)
func addCount(num int, counter chan <- int) {
time.Sleep(time.Second * 2)
counter <- num * 2
}
func main() {
counter := make(chan int)
int_slice := []int{2, 4}
for _, item := range int_slice {
go addCount(item, counter)
fmt.Println(<-counter)
}
}

Resources