匿名结构体
最常见的匿名用法,不用单独定义一个结构体类型
@H_502_27@var config @H_502_27@struct {
APIKey @H_502_27@string
OAuthConfig oauth.Config
}
config.APIKey = "BADC0C0A"
匿名结构体定义时并初始化
@H_502_27@data := struct { Title string Users []*User }{ title,users,}
err := tmpl.Execute(w,@H_502_27@data)
匿名结构体slice定义并初始化
@H_502_27@var indexRuneTests = []@H_502_27@struct {
s string
rune rune
out int
}{
{"a A x",'A', 2},{"some_text=some_value",'=', 9},{"☺a",'a', 3},{"a☻☺b",'☺', 4},}
嵌套互斥锁
var hits struct {
sync.Mutex
n int
}
hits.Lock()
hits.n++
hits.Unlock()
嵌套结构体
@H_502_27@type Item struct { Title string URL string }
@H_502_27@type Response struct { Data struct { Children []struct { Data Item }
}
}
命令行 go doc
在命令行中,可以通过go doc 查看包相关接口信息
wdy@wdy:~/learn/program-learn/golang$ go doc sync
package sync // import "sync"
Package sync provides basic synchronization primitives such as mutual
exclusion locks. Other than the Once and WaitGroup types,most are intended
@H_502_27@for use by low-level @H_502_27@library routines. Higher-level synchronization is
better done via channels and communication.
Values containing the types defined @H_502_27@in this package should not be copied.
func NewCond(l Locker) *Cond
type Cond struct { @H_502_27@... }
type Locker interface { @H_502_27@... }
type Mutex struct { @H_502_27@... }
type Once struct { @H_502_27@... }
type Pool struct { @H_502_27@... }
type RWMutex struct { @H_502_27@... }
type WaitGroup struct { @H_502_27@... }
wdy@wdy:~/learn/program-learn/golang$ go doc sync Mutex
type Mutex struct {
// Has unexported fields.
}
A Mutex is a mutual exclusion lock. Mutexes can be created as part of other
structures; the zero value @H_502_27@for a Mutex is an unlocked mutex.
func (m *Mutex) Lock()
func (m *Mutex) Unlock()
wdy@wdy:~/learn/program-learn/golang$ go doc sync.mutex.lock
func (m *Mutex) Lock()
Lock locks m. If the lock is already @H_502_27@in use,the calling goroutine blocks
@H_502_27@until the mutex is available.
在同一个channel上进行读写操作
battle是一个阻塞channel,当多个goroutine执行warrior的时候,最先执行到select的goroutine进入到
@H_502_27@case battle <- name:
此时其他goroutine会阻塞在select上,name进入battle的瞬间,阻塞等待的goroutine的其中一个会进入到
@H_502_27@case opponent := <-battle:
battle数据被读取后,阻塞等待的剩余的goroutine的其中一个会进入到
@H_502_27@case battle <- name:
按照如上流程反复直到所有goroutine执行完毕。
@H_502_27@var battle = make(@H_502_27@chan string)
@H_502_27@func warrior(name string,done @H_502_27@chan @H_502_27@struct{}) {
@H_502_27@select {
@H_502_27@case opponent := <-battle:
fmt.Printf("%s beat %s\n",name,opponent)
@H_502_27@case battle <- name:
// I lost :-(
}
done <- @H_502_27@struct{}{}
}
@H_502_27@func main() {
done := make(@H_502_27@chan @H_502_27@struct{})
langs := []string{"Go","C","C++","Java","Perl","Python"}
@H_502_27@for _,l := @H_502_27@range langs {
@H_502_27@go warrior(l,done)
}
@H_502_27@for _ = @H_502_27@range langs {
<-done
}
}
可以看到每次结果都是不一样的
wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
Go beat Python
C++ beat C
Java beat Perl
wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
Perl beat Java
Python beat Go
C beat C++
wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
C++ beat C
Java beat Perl
Python beat Go
wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
Go beat Python
Perl beat Java
C beat C++
wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
Python beat Go
C beat C++
Java beat Perl
wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
Go beat Python
Perl beat Java
C beat C++
wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
Go beat Python
C beat C++
Java beat Perl
利用close来向其他goroutine广播
@H_502_27@func waiter(i int,block,done @H_502_27@chan @H_502_27@struct{}) {
time.Sleep(time.Duration(rand.Intn(3000)) * time.Millisecond)
fmt.Println(i,"waiting...")
<-block
fmt.Println(i,"done!")
done <- @H_502_27@struct{}{}
}
@H_502_27@func main() {
block,done := make(@H_502_27@chan @H_502_27@struct{}),make(@H_502_27@chan @H_502_27@struct{})
@H_502_27@for i := 0; i < 4; i++ {
@H_502_27@go waiter(i,done)
}
time.Sleep(5 * time.Second)
close(block)
@H_502_27@for i := 0; i < 4; i++ {
<-done
}
}
结果
2 waiting...
1 waiting...
3 waiting...
0 waiting...
0 @H_502_27@done!
3 @H_502_27@done!
2 @H_502_27@done!
1 @H_502_27@done!
利用nil通道的特性
goroutine对于值为nil的channel进行接受或发送操作时,会永久block
@H_502_27@type Work @H_502_27@struct {
Job string
}
@H_502_27@func (w Work) Do() {
fmt.Println("do",w.Job)
}
@H_502_27@func (w Work) Refuse() {
fmt.Println(w.Job + "stopped")
}
@H_502_27@func makeWork(ch @H_502_27@chan Work) {
@H_502_27@for {
time.Sleep(500 * time.Millisecond)
ch <- Work{Job: "job"}
}
}
@H_502_27@func worker(i int,ch @H_502_27@chan Work,quit @H_502_27@chan @H_502_27@struct{}) {
@H_502_27@for {
@H_502_27@select {
@H_502_27@case w := <-ch:
@H_502_27@if quit == nil {
w.Refuse()
fmt.Println("worker",i,"refused",w)
@H_502_27@break
}
w.Do()
fmt.Println("worker","processed",w)
@H_502_27@case <-quit:
fmt.Println("worker","quitting")
quit = nil
}
}
}
结果
do job
worker 0 processed {job}
do job
worker 1 processed {job}
do job
worker 2 processed {job}
do job
worker 3 processed {job}
do job
worker 0 processed {job}
do job
worker 1 processed {job}
do job
worker 2 processed {job}
do job
worker 3 processed {job}
do job
worker 0 processed {job}
worker 0 quitting
worker 1 quitting
worker 2 quitting
worker 3 quitting
jobstopped
worker 0 refused {job}
jobstopped
worker 1 refused {job}
jobstopped
worker 2 refused {job}
jobstopped
worker 3 refused {job}