关于Golang代码片段 https://play.golang.org/p/PdJqR-pSN58 的几个问题
关于Golang代码片段 https://play.golang.org/p/PdJqR-pSN58 的几个问题 在…v, ok := m[“Barnabas”] fmt.Println(v) fmt.Println(ok) 这里的ok是什么意思?
另外,这里发生了什么:
if v, ok := m["Barnabas"]; ok {
fmt.Println(v)
但这有点偏离主题,所以我不会深入探讨
谢谢
更多关于关于Golang代码片段 https://play.golang.org/p/PdJqR-pSN58 的几个问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
是的。这是一个被选定的名称,不是保留字。
零值是什么意思?我知道它与布尔类型有关,但我对此不太理解
func main() {
fmt.Println("hello world")
}
那么Go语言的规范就与计算机科学领域的通用术语存在分歧。
NobbZ:
不,并非如此,这被称为多值赋值。
谢谢
是的。这是一个选定的名称。不是保留字。 由编写程序的人选择的吗?(看我的理解有多基础?)
那么"ok"只是老师随意选择的一个变量名,还是它在Go语言中特指某个概念?
iegomez:
对这个有了初步理解
NobbZ:
那么 Go 语言的规范就与计算机科学领域的通用术语存在分歧。
其实不然。Go 语言支持元组赋值,只是没有元组类型。但这有点偏离主题,我就不深入探讨了。
jayts:
tuple assignment
不,这不是元组赋值,而是被称为多值赋值。
如果 Go 语言支持元组,我就可以这样写 t := 1, 2 并且将 t 作为包含两个值的变量来传递。
元组是一种结构体,其字段没有名称,而是通过索引/位置来标识。
jayts:
在 Go 语言中处理这种情况的方式是,访问映射时会返回两个值。第一个是元素(可能是之前存储的值,或者由于该位置没有存储任何内容而返回的零值),同时还会返回另一个值来指示属于这两种情况中的哪一种。
这一点对我来说非常清楚。
if v, ok := m["Barnabas"]; ok {
// declare two new variables: v and ok
// if ok variable is true; then the code here will be executed
// so, it will print the v variable
fmt.Println(v)
}
这被称为"逗号ok惯用法"。"ok"不是保留字,但在Go语言中被广泛使用。
例如,在检查映射值是否包含指定键时(就像你的示例中那样)。
这被称为"逗号ok惯用法"。"ok"不是保留字,但在Go语言中被广泛使用。
例如,在检查映射值是否包含指定键时(如你的示例所示)。
if v, ok := m["Barnabas"]; ok {
// 声明两个新变量:v和ok
// 如果ok变量为true,则此处的代码将被执行
// 因此它将打印v变量
fmt.Println(v)
}
if v, ok := m["Barnabas"]; ok {
// 声明两个新变量:v和ok
// 如果ok变量为true,则此处的代码将被执行
// 因此它将打印v变量
fmt.Println(v)
}
非常有帮助
对于第一个示例,来自 Go 语言之旅(这里是相关章节):
elem, ok = m[key]
如果 key 存在于 m 中,ok 为 true。如果不存在,ok 为 false。
如果 key 不在映射中,那么 elem 是该映射元素类型的零值。
简而言之,ok(或者你给访问映射时返回的第二个值起的任何名称,它是一个 bool 类型)会告诉你该键是否存在。
在第二个示例中,Go 语言中的 if 可以在条件检查之前以一个简短语句开始。这几乎等同于以下写法:
v, ok := m[“Barnabas”]
if ok {
fmt.Println(v)
}
我说几乎是因为在后一种情况下,ok 位于其所在函数的局部作用域内,而在你的示例中(当语句是 if 的一部分时),ok 位于 if 的局部作用域内,也就是说,它不能在 if 之后使用。请参考我之前提到过这一点的帖子。同样,Go 语言之旅也提到了这一点:https://tour.golang.org/flowcontrol/6
你好 Norbert,
我直接使用了《Go 编程语言规范》中的术语。元组赋值这一术语在赋值章节中有详细说明:

Go 编程语言规范 - Go 编程语言
为了节省你的时间,我将第三个浅灰色框之后的内容放在这里:
元组赋值将多值操作中的各个元素分配给一个变量列表。它有两种形式。第一种形式中,右侧操作数是单个多值表达式,例如函数调用、通道或映射操作,或类型断言。左侧的操作数数量必须与值的数量匹配。例如,如果
f是返回两个值的函数:x, y = f()将第一个值赋给
x,第二个值赋给y。第二种形式中,左侧的操作数数量必须等于右侧的表达式数量,每个表达式必须是单值的,并且右侧的第 n 个表达式赋给左侧的第 n 个操作数:one, two, three = '一', '二', '三'
在Go语言中,当从map中通过键获取值时,可以返回两个值:第一个是键对应的值(如果键不存在则返回该值类型的零值),第二个是一个布尔值,表示该键是否存在于map中。
在你的代码片段中:
v, ok := m["Barnabas"]
fmt.Println(v)
fmt.Println(ok)
这里的ok是一个布尔变量,如果map m中存在键"Barnabas",则ok的值为true,否则为false。
对于第二个代码片段:
if v, ok := m["Barnabas"]; ok {
fmt.Println(v)
}
这是一个if语句的初始化语句用法。这里发生了以下操作:
- 执行初始化语句:
v, ok := m["Barnabas"],从map中获取值并检查键是否存在 - 条件判断:
ok(如果为true则执行if块内的代码) - 只有当键
"Barnabas"存在于map中时,才会打印对应的值v
这种写法是Go语言中检查map中键是否存在并安全访问值的常用模式。如果键不存在,ok为false,if块内的代码不会执行,避免了访问不存在的键导致的意外行为。
示例:
m := map[string]int{
"Alice": 25,
"Bob": 30,
}
// 键存在的情况
if v, ok := m["Alice"]; ok {
fmt.Println(v) // 输出: 25
}
// 键不存在的情况
if v, ok := m["Barnabas"]; ok {
fmt.Println(v) // 这行不会执行
}


