[Go]程序结构——赋值

来源:互联网 发布:highcharts more.js 编辑:程序博客网 时间:2024/05/16 12:15

使用赋值语句可以更新一个变量的值,最简单的赋值语句是将变量放在“=”左边,新值放在右边。

x = 1                       // 命名变量的赋值*p = true                   // 通过指针间接赋值person.name = "bob"         // 结构体字段赋值count[x] = count[x] * scale // 数组、slice或map的元素赋值
复合赋值:

count[x] *= scale
数值变量也可以支持++递增和--递减:

v := 1v++    // 等价方式 v = v + 1;v 变成 2v--    // 等价方式 v = v - 1;v 变成 1
元组赋值

元组赋值是另一种形式的赋值语句,它允许同时更新多个变量的值。在赋值之前,赋值语句右边的所有表达式将会先进行求值,然后再统一更新左边的对应变量。这对于处理有些同时出现在元组赋值语句左右两边的变量很有帮助,例如,我们可以这样交换两个变量的值:

x, y = y, xa[i], a[j] = a[j], a[i]
或者是计算两个整数的最大公约数:

func gcd(x, y int) int {    for y != 0 {        x, y = y, x%y    }    return x}
或者是计算斐波拉契数列:

func fib(n int) int {    x, y := 0, 1    for i := 0; i < n; i++ {        x, y = y, x+y    }    return x}
元素赋值也可以使一系列琐碎赋值更加紧凑:

i, j, k = 2, 3, 5
但如果表达式太复杂的话,应该尽量避免过度使用元组赋值,因为每个变量单独赋值的写法可读性更好。

有些表达式会产生多个值,比如调用一个有多个返回值的函数。当这样一个函数出现在元组赋值右边的表达式中时,左边变量的数据必须和右边一致。

f, err = os.Open("foo.txt") // function call returns two values
通常,这类函数会用额外的返回值来表达某种错误类型,例如os.Open用额外的返回值返回一个error类型的错误。还有一些会返回布尔值,通常称为ok。在后面会看到三个操作都是类似的用法:map查找、类型断言或通道接收。

v, ok = m[key]             // map lookupv, ok = x.(T)              // type assertionv, ok = <-ch               // channel receive
对于map查找、类型断言或通道接收,并不一定产生两个结构,也可能只产生一个结果。对于返回一个结果的情形,map查找失败时会返回零值,类型断言失败时会发送运行时panic异常、通道接收失败时会返回零值(阻塞不算失败)。例如下面的例子:

v = m[key]                // map查找,失败时返回零值v = x.(T)                 // type断言,失败时panic异常v = <-ch                  // 管道接收,失败时返回零值(阻塞不算是失败)_, ok = m[key]            // map返回2个值_, ok = mm[""], false     // map返回2个值_ = mm[""]                // map返回1个值
和变量声明一样,可以用下划线空白标识符“_”来丢弃不需要的值。

_, err = io.Copy(dst, src) // 丢弃字节数_, ok = x.(T)              // 只检测类型,忽略具体值
可赋值性

赋值语句是显示的赋值形式,但是程序中海油很多其他地方会发生隐式的赋值行为:函数调用会隐式地将实参赋值给形参,一个返回语句会隐式地返回操作的结果,一个复合类型的字面量也会产生赋值行为。例如下面的语句:

medals := []string{"gold", "silver", "bronze"}
隐式地对slice的每个元素进行赋值操作,类似这样写的:

medals[0] = "gold"medals[1] = "silver"medals[2] = "bronze"
map和chan的元素,虽然不是普通的变量,但也有类似的隐式赋值。

无论是隐式还是显式地赋值,在赋值语句的左边和右边都必须有相同的数据类型,只有右边的值对于左边的变量是可赋值的,赋值语句才是允许的。

可赋值性的规则对于不同类型有着不同要求,对每个新类型特殊的地方会专门解释。对于目前我们已经讨论的类型,它的规则是最简答的:类型必须完全匹配,nil可以赋值给任何指针或引用类型的变量。常量则有更灵活的赋值规则,因为这样可以避免不必要的显示的类型转换。

对于两个值是否可以判等,也和可赋值性有关:对于任何类型的值得判等,第二个值 必须是对 第一个值 对应类型的变量是可赋值的。和前面一样,对每个新类型比较特殊的地方做专门的解释。