欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

020-赋值(Assignment)

程序员文章站 2022-07-16 14:49:37
...

同其它语言一样,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 中,有些表达式会产生多个值。比如:

x, y, z := 10, 20, 30

有些函数也会返回多个值。比如:

n, err := io.Copy(dst, src)

还有 map 的查找,类型断言,通道接收也会返回多个值(也会返回一个值)。

v, ok = m["name"] // 如果没有查找到 okfalse
v, ok = x.(int)   // 断言 x 的类型是否为 int,这是类型断言语法
v, ok = <-ch      // 如果通道已经关闭,okfalse

下面的例子说明了 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 =
}

上面的程序输出结果如下:


020-赋值(Assignment)
图1 map 查找输出结果

上面的例子告诉我们,map 查找如果只返回一个值,我们没有办法判断该值是否在 map 中。所以只能使用 map 查找返回的第 2 个值来判断 map 中是否存在该值。一般可以这样使用:

if v, ok := m["name"]; !ok {
    fmt.Println("name not existed")
}

3. 总结

  • 掌握 go 的赋值方法
  • 掌握 map 查找如何判断 key 是否存在,类似的还有类型断言,通道接收值