golang的struct{}類型channel
struct{}是個什么鬼
之前看代碼的時候發(fā)現(xiàn)有如下定義的channel,就覺得很詫異
var ch chan struct{}
這其中,struct{}是個什么鬼。
實(shí)際上struct{}就是一種普通數(shù)據(jù)類型,只是沒有具體的值而已。
常用用法
通常struct{}類型channel的用法是使用同步,一般不需要往channel里面寫數(shù)據(jù),只有讀等待,而讀等待會在channel被關(guān)閉的時候返回。
package main
import (
"time"
"log"
)
var ch chan struct{} = make(chan struct{})
func foo() {
log.Println("foo() 111");
time.Sleep(5 * time.Second)
log.Println("foo() 222");
close(ch)
log.Println("foo() 333");
}
func main() {
log.Println("main() 111");
go foo()
log.Println("main() 222");
<-ch
log.Println("main() 333");
}
運(yùn)行結(jié)果為
2018/04/12 06:46:33 main() 111
2018/04/12 06:46:33 main() 222
2018/04/12 06:46:33 foo() 111
2018/04/12 06:46:38 foo() 222
2018/04/12 06:46:38 foo() 333
2018/04/12 06:46:38 main() 333
在main函數(shù)里面ch讀操作一直等待foo調(diào)用close(ch)才返回。
注意啊,channel對象一定要make出來才能使用。
往chann struct{}寫入數(shù)據(jù)
另一個問題,我們能不能往struct{}類型的channel里面寫數(shù)據(jù)呢,答案當(dāng)然也是可以的。
package main
import (
"time"
"log"
)
var ch chan struct{} = make(chan struct{})
func foo() {
ch <- struct{}{}
log.Println("foo() 111");
time.Sleep(5 * time.Second)
log.Println("foo() 222");
close(ch)
log.Println("foo() 333");
}
func main() {
log.Println("main() 111");
go foo()
log.Println("main() 222");
<-ch
log.Println("main() 333");
}
在foo()入口處給ch賦了一個值
注意寫法是"struct{}{}",第一個"{}"對表示類型,第二個"{}"對表示一個類型對象實(shí)例。
運(yùn)行結(jié)果:
2018/04/12 06:50:16 main() 111
2018/04/12 06:50:16 main() 222
2018/04/12 06:50:16 foo() 111
2018/04/12 06:50:16 main() 333
由于在foo()啟動的時候往ch里面寫入了一個對象,所以在main()函數(shù)里面不需要等待close(ch)就能拿到一個值,因此main()函數(shù)可以馬上退出,不需要等到foo()的Sleep()完成。
帶緩沖的chan struct{}數(shù)據(jù)讀寫
另外也可以定義帶緩沖的channel
package main
import (
"time"
"log"
)
var ch chan struct{} = make(chan struct{}, 2)
func foo() {
ch <- struct{}{}
log.Println("foo() 000");
ch <- struct{}{}
log.Println("foo() 111");
time.Sleep(5 * time.Second)
log.Println("foo() 222");
close(ch)
log.Println("foo() 333");
}
func main() {
var b struct{}
log.Println("main() 111");
go foo()
log.Println("main() 222");
a := <-ch
log.Println("main() 333", a);
b = <-ch
log.Println("main() 444", b);
c := <-ch
log.Println("main() 555", c);
}
運(yùn)行結(jié)果為
2018/04/12 06:58:06 main() 111
2018/04/12 06:58:06 main() 222
2018/04/12 06:58:06 foo() 000
2018/04/12 06:58:06 foo() 111
2018/04/12 06:58:06 main() 333 {}
2018/04/12 06:58:06 main() 444 {}
2018/04/12 06:58:11 foo() 222
2018/04/12 06:58:11 foo() 333
2018/04/12 06:58:11 main() 555 {}
帶兩個緩沖大小的channel;
另外我們可以看到,其實(shí)也可以從channel里面讀出數(shù)據(jù)來,但是這種數(shù)據(jù)顯然沒有實(shí)際意義。