类似

1
2
3
if _, ok := map[key]; ok {
//存在
}

这样的编译器简化后的判断代码(实际应该是一种语法糖),在Go中非常常用. 一般称为称 “ok判别式”,但其实这个变量的名称可以随意取,不一定是”ok”


检测map中是否存在某个key:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import "fmt"

func main() {

isVip := make(map[string]bool)

isVip["张三"] = true
isVip["李四"] = false

if val, ok := isVip["王五"]; ok {
fmt.Printf("王五是否为vip:%t\n", val)
} else {
fmt.Println("王五不是注册用户")
}

if val, ok := isVip["李四"]; ok {
fmt.Printf("李四是否为vip:%t\n", val)
} else {
fmt.Println("李四不是注册用户")
}

}

输出为:

1
2
王五不是注册用户
李四是否为vip:false




类型断言:检测一个接口类型的变量i,是否包含了类型T


1
2
3
4
5
if value, ok := i.(T); ok {
fmt.Println(value)
} else{
// 接口类型i没有包含类型T
}

更多可参见:

Golang类型断言




检测一个通道是否关闭


更确切说,实际是检测一个通道还能否继续读取.

即对于有缓存的通道ch,在close(ch)之后,如果还有未读取出的变量,ok判别式的值为true.

即改为: 检测一个通道能否继续读取更为合适



检测是否还能从通道中读取出传递的值


可参考:

golang之channel入门


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
package main

import "fmt"

func main() {

ch := make(chan int, 2)

fmt.Println(ch)

ch <- 271828

fmt.Println(<-ch) //这样也相当于进行了读取,channel里的缓存空间又会增加1个单位

ch <- 271828 //#1
ch <- 271828 //#2

//channel<-271828 //如果继续写入,超过缓存值2,则会报fatal error: all goroutines are asleep - deadlock!

close(ch)

//关闭之后尝试进行读取
//channel关闭之后,仍然可以从channel中读取剩余的数据,直到数据全部读取完成。
//读取完后继续读,得到的将是对应类型的零值.

if val, ok := <-ch; ok {
fmt.Println("值为:", val)
} else {
fmt.Println("通道已被关闭,无法再进行读取")
}

}

输出为i:

1
2
3
0xc00009a000
271828
值为: 271828


而如果将两行写缓存的代码注释掉,即注释掉#1和#2,则输出结果为:

1
2
3
0xc000090000
271828
通道已被关闭,无法再进行读取


即如果还能读出缓存的值,即便通道已经被关闭,ok的值依然会是true



参考:

golang中逗号ok模式_转

Go语言那些返回值数量变化的语句?