Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Всё это позволяет отловить некоторые ошибки на этапе компиляции.
func main() {
done := make(chan struct{})
go func() {
// stuff
done <- struct{}
}()
<- done
}
Размер bool зависит от платформы, да, обычно, это не тот случай, когда следует беспокоиться о размере. Но всё же существует способ ничего не отправлять, а если точнее — то отправлять ничего (если быть ещё точнее, то речь о пустой структуре).
done := make(chan struct{})
// [...]
done < — struct{}{}
done := make(chan interface{})
//
done <- nil
done := make(chan interface{})
//
close(done)
// в родителе
select {
case _,ok := <- done:
if !ok {
// канал закрыт
}
}
ch := make(chan int)
// ...
select {
val, ok := <- ch:
// обработка значения
// если канал пуст - управление возвращается коду
// если канал закрыт - val == nil, ok == false
}
interface{} или bool. В любом случае — это какие-то значения. Вот например размеры play.golang.org, и nil — это тоже значение, в данном случае. Суть в том, что любое количество struct{} будет занимать 0 памяти, а указатель на переменную содержащую struct{}{} будет всегда один и тот же, для всех таких переменных. Иными словами — это ничего в классическом понимании. С таким же успехом, вместо inteface{} можно пулять любой референсный тип, но опять же зачем?nil — это нулевой указатель, всё верно. И он занимает uintptr места. Указатель на struct{}{} будет занимать столько же места, столько же места будет занимать []byte или &struct{ A, B, C int }. Я не призываю использовать указатель на struct{}{}, ибо это вряд ли когда пригодиться. Но хочу подчеркнуть — что struct{}{} — всегда один и тот же экземпляр. Вот напримерvar a, b struct{}
a == b // true
&a == &b // true
На play.golang.org с раскрытием значения &struct{}{}.interface{}, кстати — это что-то вроде указателя на структуру вида struct{ typePtr, valPrt }. Вот референс (англ.). Разумеется на несуществующий interface{} будет указывать nil ровно как и на любой другой референсный тип.struct{}{} — то приложение выжрет всю память, или будет жёстко тормозить. Вот есть такая фишка как struct{}{} — это основной посыл. И эта struct{}{} применима только для пересылки по каналу, когда по сути не важно, что пересылать. В коде такие пересылки будут явно означать (при просмотре), что речь не о передаче данных, а о каком-то сигнале/событии.LockOSThread не заставляет всю программу выполняться в одном треде, а только текущую горутину. Ща исправлю, на более корректное высказывание. Спасибо, Вы очень внимательны.Всё время мысленно провожу аналогию с POSIX threads — а это отдельные процессы (по крайней мере в Linux).
Но более того, есть публикации, которые утверждают, что горутины даже не являются потоками ядра, а являются ещ более легковесными механизмами пространства пользователя.И это так. Но это не значит, что горутины не используют треды ОС.
If a goroutine is blocking, the runtime will start a new OS thread to handle the other goroutines until the blocking one stops blocking.Например для
package main
import "time"
func comm() (chan<- struct{}, <-chan struct{}) {
c := make(chan struct{})
return c, c
}
func main() {
in, out := comm()
go func(done chan<- struct{}) {
time.Sleep(30*time.Second)
done <- struct{}{}
}(in)
time.Sleep(30*time.Second)
<-out
}
ps -o nlwp $PID будет 4.time.Sleep следовало использовать, напримерbuf := make([]byte, 1024)
_, _ = syscall.Read(0, buf) // чтение STDIN
Go, практика асинхронного взаимодействия