020-赋值(Assignment)
原创
©著作权归作者所有:来自51CTO博客作者mb63083a7dd962a的原创作品,请联系作者获取转载授权,否则将追究法律责任
同其它语言一样,go 的赋值运算符也是 =
,不过 go 的 =
更加强大,它支持元组赋值(Tuple Assignment),有人称其为平行赋值。
同样在 go 里,要求 =
左侧的变量类型和右侧值的类型匹配,否则会编译不通过。
1. 赋值
举几个例子:
var x int = 10
var y int = 10
x++ // ok
y = x++ // not ok
x *= 10 // ok, same as x = x * 10
x-- // ok
++x // not ok
--x // not ok
x, y = 30, 40 // ok
x, y = y, x // ok, swap value
- go 的
x++
不是表达式,而是语句(go 应该是想避免不必要的争论,干脆就不支持它吧),因此y = x++
这种写法是不正确的。 - go 不支持
++x
和--x
写法。(有一个x++
,x--
就够了,干嘛搞那么多?)
在 c/c++ 语言的论坛或一些群里总看到有人讨论类似 y = x++ + ++x
的结果是啥,甚至搬出汇编语言来强行解释结果。借用某大佬的一句话:用汇编学 C 就像是根据大便的位置来判断自己屁眼在哪……(有些物理系的同学可能会喷我,抱歉。。。)
在 go 里这种无聊的讨论永远不存在,go 从源头将这种无意义的争论扼杀在了摇篮里。
2. 元组赋值
在 go 中,有些表达式会产生多个值。比如:
有些函数也会返回多个值。比如:
n, err := io.Copy(dst, src)
还有 map 的查找,类型断言,通道接收也会返回多个值(也会返回一个值)。
v, ok = m["name"] // 如果没有查找到 ok 为 false
v, ok = x.(int) // 断言 x 的类型是否为 int,这是类型断言语法
v, ok = <-ch // 如果通道已经关闭,ok 为 false
下面的例子说明了 map 查找可以返回一个值,也可以返回 2 个值:
package main
import "fmt"
func main() {
m := make(map[string]string)
m["name"] = "allen"
m["sex"] = ""
v, ok := m["name"]
fmt.Printf("v = %s, ok = %v\n", v, ok) // v = allen, ok = true
v, ok = m["age"]
fmt.Printf("v = %s, ok = %v\n", v, ok) // v = , ok = false
v, ok = m["sex"]
fmt.Printf("v = %s, ok = %v\n", v, ok) // v = , ok = true
v = m["name"]
fmt.Printf("v = %s\n", v) // v = allen
v = m["age"]
fmt.Printf("v = %s\n", v) // v =
v = m["sex"]
fmt.Printf("v = %s\n", v) // v =
上面的程序输出结果如下:
图1 map 查找输出结果
上面的例子告诉我们,map 查找如果只返回一个值,我们没有办法判断该值是否在 map 中。所以只能使用 map 查找返回的第 2 个值来判断 map 中是否存在该值。一般可以这样使用:
if v, ok := m["name"]; !ok {
fmt.Println("name not existed")
}
3. 总结
- 掌握 go 的赋值方法
- 掌握 map 查找如何判断 key 是否存在,类似的还有类型断言,通道接收值