我是靠谱客的博主 动听身影,这篇文章主要介绍你可能不知道的关于golang 的10件事情,现在分享给大家,希望可以做个参考。

    • 匿名结构体
    • 命令行 go doc
    • 在同一个channel上进行读写操作
    • 利用close来向其他goroutine广播
    • 利用nil通道的特性
    • 后记

英文原文

匿名结构体

最常见的匿名用法,不用单独定义一个结构体类型

复制代码
1
2
3
4
5
6
7
var config struct { APIKey string OAuthConfig oauth.Config } config.APIKey = "BADC0C0A"

匿名结构体定义时并初始化

复制代码
1
2
3
4
5
6
7
8
data := struct { Title string Users []*User }{ title, users, } err := tmpl.Execute(w, data)

匿名结构体slice定义并初始化

复制代码
1
2
3
4
5
6
7
8
9
10
var indexRuneTests = []struct { s string rune rune out int }{ {"a A x", 'A', 2}, {"some_text=some_value", '=', 9}, {"☺a", 'a', 3}, {"a☻☺b", '☺', 4}, }

嵌套互斥锁

复制代码
1
2
3
4
5
6
7
8
var hits struct { sync.Mutex n int } hits.Lock() hits.n++ hits.Unlock()

嵌套结构体

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
type Item struct { Title string URL string } type Response struct { Data struct { Children []struct { Data Item } } }

命令行 go doc

在命令行中,可以通过go doc 查看包相关接口信息

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 for use by low-level library routines. Higher-level synchronization is better done via channels and communication. Values containing the types defined in this package should not be copied. func NewCond(l Locker) *Cond type Cond struct { ... } type Locker interface { ... } type Mutex struct { ... } type Once struct { ... } type Pool struct { ... } type RWMutex struct { ... } type WaitGroup struct { ... }
复制代码
1
2
3
4
5
6
7
8
9
10
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 for a Mutex is an unlocked mutex. func (m *Mutex) Lock() func (m *Mutex) Unlock()
复制代码
1
2
3
4
wdy@wdy:~/learn/program-learn/golang$ go doc sync.mutex.lock func (m *Mutex) Lock() Lock locks m. If the lock is already in use, the calling goroutine blocks until the mutex is available.

在同一个channel上进行读写操作

battle是一个阻塞channel,当多个goroutine执行warrior的时候,最先执行到select的goroutine进入到

复制代码
1
case battle <- name:

此时其他goroutine会阻塞在select上,name进入battle的瞬间,阻塞等待的goroutine的其中一个会进入到

复制代码
1
case opponent := <-battle:

battle数据被读取后,阻塞等待的剩余的goroutine的其中一个会进入到

复制代码
1
case battle <- name:

按照如上流程反复直到所有goroutine执行完毕。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var battle = make(chan string) func warrior(name string, done chan struct{}) { select { case opponent := <-battle: fmt.Printf("%s beat %sn", name, opponent) case battle <- name: // I lost :-( } done <- struct{}{} } func main() { done := make(chan struct{}) langs := []string{"Go", "C", "C++", "Java", "Perl", "Python"} for _, l := range langs { go warrior(l, done) } for _ = range langs { <-done } }

可以看到每次结果都是不一样的

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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广播

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func waiter(i int, block, done chan struct{}) { time.Sleep(time.Duration(rand.Intn(3000)) * time.Millisecond) fmt.Println(i, "waiting...") <-block fmt.Println(i, "done!") done <- struct{}{} } func main() { block, done := make(chan struct{}), make(chan struct{}) for i := 0; i < 4; i++ { go waiter(i, block, done) } time.Sleep(5 * time.Second) close(block) for i := 0; i < 4; i++ { <-done } }

结果

复制代码
1
2
3
4
5
6
7
8
2 waiting... 1 waiting... 3 waiting... 0 waiting... 0 done! 3 done! 2 done! 1 done!

利用nil通道的特性

goroutine对于值为nil的channel进行接受或发送操作时,会永久block

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
type Work struct { Job string } func (w Work) Do() { fmt.Println("do", w.Job) } func (w Work) Refuse() { fmt.Println(w.Job + "stopped") } func makeWork(ch chan Work) { for { time.Sleep(500 * time.Millisecond) ch <- Work{Job: "job"} } } func worker(i int, ch chan Work, quit chan struct{}) { for { select { case w := <-ch: if quit == nil { w.Refuse() fmt.Println("worker", i, "refused", w) break } w.Do() fmt.Println("worker", i, "processed", w) case <-quit: fmt.Println("worker", i, "quitting") quit = nil } } }

结果

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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}

后记

之前一直在CSDN上写文章,后面会逐步转换到简书上,还请大家多多支持。

最后

以上就是动听身影最近收集整理的关于你可能不知道的关于golang 的10件事情的全部内容,更多相关你可能不知道的关于golang内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(113)

评论列表共有 0 条评论

立即
投稿
返回
顶部