https:\/\/golang.org\/pkg\/time\/#Time.After<\/a><\/p>\n\n\n\nLet's see a program of select with timeout<\/p>\n\n\n\n
package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc main() {\n\tch1 := make(chan string)\n\tgo goOne(ch1)\n\n\tselect {\n\tcase msg := <-ch1:\n\t\tfmt.Println(msg)\n\tcase <-time.After(time.Second * 1):\n\t\tfmt.Println(\"Timeout\")\n\t}\n}\n\nfunc goOne(ch chan string) {\n\ttime.Sleep(time.Second * 2)\n\tch <- \"From goOne goroutine\"\n}<\/code><\/pre>\n\n\n\nOutput<\/strong><\/p>\n\n\n\nTimeout<\/code><\/pre>\n\n\n\nIn the above select statement we are waiting for receive operation to complete on ch1<\/strong>. In other case statement we have time.After<\/strong> with the duration of 1 second. So essentially this select statement will wait for at least 1 second for receive operation to complete on ch1<\/strong> and after that the time.After <\/strong>case statement will be executed. We have put a timeout of more than 1 seconds in the goOne<\/strong> function and hence we see the time.After <\/strong>statement getting executed and<\/p>\n\n\n\nTimeout<\/code><\/pre>\n\n\n\ngetting printed as output<\/p>\n\n\n\n
<\/span>Empty select<\/strong><\/span><\/h1>\n\n\n\nSelect block without any case statement is empty select. The empty select will block forever as there is no case statement to execute. It is also one of the way for a goroutine to wait indefinitely. But if this empty select is put in the main goroutine then it will cause a deadlock. Let's see a program<\/p>\n\n\n\n
package main\n\nfunc main() {\n select {}\n}<\/code><\/pre>\n\n\n\nOutput<\/strong><\/p>\n\n\n\nfatal error: all goroutines are asleep - deadlock!<\/code><\/pre>\n\n\n\nIn the above program we have empty select and hence it results in a deadlock that is why you see the output as below<\/p>\n\n\n\n
fatal error: all goroutines are asleep - deadlock!<\/code><\/pre>\n\n\n\n<\/span>Select statement with an infinite for loop outside<\/strong><\/span><\/h1>\n\n\n\nWe can have infinite for loop outside a select statement. This will cause the select statement to execute indefinite number of times.So when using for statement with infinite loop outside the select statement, we need to have a way yo break out of the for loop. One of the use case of having infinite for loop outside select statement could be that you are waiting for multiple operations to receive on the same channel for a certain time. See below example<\/p>\n\n\n\n
package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc main() {\n\tnews := make(chan string)\n\tgo newsFeed(news)\n\n\tprintAllNews(news)\n}\n\nfunc printAllNews(news chan string) {\n\tfor {\n\t\tselect {\n\t\tcase n := <-news:\n\t\t\tfmt.Println(n)\n\t\tcase <-time.After(time.Second * 1):\n\t\t\tfmt.Println(\"Timeout: News feed finished\")\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc newsFeed(ch chan string) {\n\tfor i := 0; i < 2; i++ {\n\t\ttime.Sleep(time.Millisecond * 400)\n\t\tch <- fmt.Sprintf(\"News: %d\", i+1)\n\t}\n}<\/code><\/pre>\n\n\n\nOutput<\/strong><\/p>\n\n\n\nNews: 1\nNews: 2\nTimeout: News feed finished<\/code><\/pre>\n\n\n\nIn the above program, we have created a channel named news<\/strong> which will hold data of string type. Then we pass this channel to the newsfeed<\/strong> function which is pushing the news feed to this channel . In the select statement, we are receiving the news feed from the news<\/strong> channel. This select statement is inside an infinite for loop so the select statement will be executed multiple times until we exit out of for loop . We also have time.After <\/strong>with a duration for 1 second as one of the case statements. So this set up will receive all the news from the news<\/strong> channel for 1 second and then exit. <\/p>\n\n\n\n