GO的第二天,赋值和类型

Mr_J · · 618 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

元组赋值

赋值,一听这个词,感觉什么都不用说了,就是简单!不过Go还提供了一个元组赋值。元组赋值是另一种形式的赋值语句,它允许同时更新多个变量的值。在赋值之前,赋值语句右边的所有表达式将会先进行求值,然后再统一更新左边对应变量的值。不BB,先看代码:

// 交换两个变量的值
x, y = y, x

a[i], a[j] = a[j], a[i]

计算两个整数值的的最大公约数(GCD)

func gcd(x, y int) int {
    for y != 0 {
        x, y = y, x%y
    }
    return x
}

计算斐波纳契数列(Fibonacci)的第N个数

func fib(n int) int {
    x, y := 0, 1
    for i := 0; i < n; i++ {
        x, y = y, x+y
    }
    return x
}

是不是很方便?如果你用php去写,是不是这样写 list ( $a, $b ) = array ($b, $a ); 。感受一下

可赋值性

可赋值性的规则对于不同类型有着不同要求。对于目前我们已经讨论过的类型,它的规则是简单的:类型必须完全匹配,nil可以赋值给任何指针或引用类型的变量。

类型

一个类型声明语句创建了一个新的类型名称,和现有类型具有相同的底层结构。新命名的类型提供了一个方法,用来分隔不同概念的类型,这样即使它们底层类型相同也是不兼容的。

type 类型名字 底层类型

类型声明语句一般出现在包一级,因此如果新创建的类型名字的首字符大写,则在外部包也可以使用。
为了说明类型声明,我们将不同温度单位分别定义为不同的类型:

package main

import "fmt"

type Celsius float64    // 摄氏温度
type Fahrenheit float64 // 华氏温度

const (
    AbsoluteZeroC Celsius = -273.15 // 绝对零度
    FreezingC     Celsius = 0       // 结冰点温度
    BoilingC      Celsius = 100     // 沸水温度
)

func main() {
    
    fmt.Printf("%g\n", BoilingC - FreezingC)    // "100" °C
    boilingF := CToF(BoilingC)
    fmt.Printf("%g\n", boilingF - CToF(FreezingC))  // "180" °F
    fmt.Printf("%g\n", boilingF - FreezingC)  // mismatched types Fahrenheit and Celsius

    var c Celsius
    var f Fahrenheit
    fmt.Println(c == 0)          // "true"
    fmt.Println(f >= 0)          // "true"
    // fmt.Println(c == f)          // mismatched types Fahrenheit and Celsius
    fmt.Println(c == Celsius(f)) // "true"!
    
}

func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) }

func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) }

我们声明了两种类型:Celsius和Fahrenheit分别对应不同的温度单位。它们虽然有着 相同的底层类型float64 ,但是它们是 不同的数据类型 ,因此它们 不可以 被相互比较或混在一个表达式运算。

对于每一个类型T,都有一个对应的类型转换操作T(x),用于将x转为T类型(如果T是指针类型,可能会需要用小括弧包装T,比如(*int)(0))。只有当两个类型的 底层基础类型相同 时,才允许这种转型操作,或者是两者都是指向 相同底层结构 的指针类型,这些转换只改变类型而不会影响值本身。如果x是可以赋值给T类型的值,那么x必然也可以被转为T类型

下面的声明语句,Celsius类型的参数c出现在了函数名的前面,表示声明的是Celsius类型的一个名叫String的方法,该方法返回该类型对象c带着°C温度单位的字符串:

func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }

c := FToC(212.0)
fmt.Println(c.String()) // "100°C"
fmt.Printf("%v\n", c)   // "100°C"; no need to call String explicitly
fmt.Printf("%s\n", c)   // "100°C"
fmt.Println(c)          // "100°C"
fmt.Printf("%g\n", c)   // "100"; does not call String
fmt.Println(float64(c)) // "100"; does not call String

参考

《GO语言圣经》


有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:Mr_J

查看原文:GO的第二天,赋值和类型

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

618 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传