前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【初识Go】| Day3 变量、常量、枚举(iota)

【初识Go】| Day3 变量、常量、枚举(iota)

原创
作者头像
yussuy
修改2020-12-17 09:57:34
4150
修改2020-12-17 09:57:34
举报

变量

变量,计算机语言能存储计算结果或表示值的抽象概念。可以通过变量名访问,变量名由字母、数字、下划线组成,其中首个字符不能为数字

var 声明语句可以创建一个特定类型的变量,然后给变量附加一个名字,并且设置变量的初始值。变量声明的一般语法如下:

代码语言:txt
复制
var 变量名字 类型 = 表达式
  1. 其中”类型”或“=表达式”两个部门可以省略其中的一个。
  2. 如果省略类型信息,那么将根据初始化表达式推导变量的类型信息。
  3. 如果初始化表达式被省略,那么将用零值初始化该变量。
  • 数值类型变量对应零值是0;
  • 布尔类型变量对应零值是false;
  • 字符串类型对应的零值是空字符串;
  • 接口或引用类型(包含slice、指针、map、chan和函数)变量对应的零值是nil。
  • 数组或结构体等聚合类型对应的零值是每个元素或字段都是对应该类型的零值。

**零值初始化机制可以确保每个声明的变量总是有一个良好定义的值,因此在 Go 语言中不存在未初始化的变量。**

代码语言:txt
复制

var s string

fmt.Print(s) // ""

var i, j, k int // int, int, int, int

var b, f, s = true, 2.3, "four" // bool, float64, string

代码语言:txt
复制

一组变量也可以通过调用一个函数,由函数返回的多个返回值初始化:

代码语言:txt
复制

var f, err = os.Open(name) // os.Open returns a file and an erro

代码语言:txt
复制

简短变量声明

在函数内部,有一种称为简短变量声明语句的形式可用于声明和初始化局部变量。它以 “名字 := 表达式” 形式声明变量,变量的类型根据表达式来自动推导。

代码语言:txt
复制

anim := gif.GIF{LoopCount: nframes}

freq := rand.Float64() * 3.0

t := 0.0

代码语言:txt
复制

因为简洁和灵活的特点,**简短变量声明被广泛用于大部分的局部变量的声明和初始化。**var 形式的声明语句往往是用于需要显式指定变量类型地方,或者因为变量稍后会被重新赋值而初始值无关紧要的地方。

代码语言:txt
复制

i := 100 // an int

var boiling float64 = 100 // a float64

var names []string

var err erro

var p Point

代码语言:txt
复制

和 var 形式声明语句一样,简短变量声明语句也可以用来声明和初始化一组变量:

代码语言:txt
复制

i, j := 0, 1

代码语言:txt
复制

但是这种同时声明多个变量的方式应该限制只在可以提高代码可读性的地方使用,比如 for 语句的循环的初始化语句部分。

和普通 var 形式的变量声明语句一样,简短变量声明语句也可以用函数的返回值来声明和初始化变量。简短变量声明左边的变量可能并不是全部都是刚刚声明的。如果有一些已经在相同的词法域声明过了(§2.7),那么简短变量声明语句对这些已经声明过的变量就只有赋值行为了。

代码语言:txt
复制

in, err := os.Open(infile)

// ...

out, err := os.Create(outfile)

代码语言:txt
复制

简短变量声明语句中必须至少要声明一个新的变量,下面的代码将不能编译通过:

代码语言:txt
复制

f, err := os.Open(infile)

// ...

f, err := os.Create(outfile) // compile error: no new variables

代码语言:txt
复制

简短变量声明语句只有对已经在同级词法域声明过的变量才和赋值操作语句等价,如果变量是在外部词法域声明的,那么简短变量声明语句将会在当前词法域重新声明一个新的变量。

注:

  1. ":=" 赋值操作符,高效创建新变量,初始化声明:a := 50 或 b := false,a 和 b 的类型(int 和 bool)将由编译器自动推断。
  2. 这是使用变量的首选形式,但是它只能被用在函数体内,而不可以用于全局变量的声明与赋值。
  3. 在相同的代码块中,我们不可以再次对于相同名称的变量使用初始化声明,但可以赋值;
  4. 声明了一个局部变量却没有在相同的代码块中使用它,同样会得到编译错误
  5. 全局变量可以声明但不用。
  6. _ 实际上是一个只写变量,你不能得到它的值。这样做是因为 Go 语言中必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值。

常量

常量是一个简单值的标识符,在程序运行时,不会被修改的量。数据类型只可以是**布尔型、数字型(整数型、浮点型和复数)和字符串型**。常量的定义格式:(省略类型说明符 type,因为编译器可以根据变量的值来推断其类型。)

代码语言:txt
复制
// const identifier [type] = value

const b = "abc"

const c\_name1, c\_name2 = value1, value2

const pi = 3.14159 // approximately; math.Pi is a better approximation

常用于批量声明:

代码语言:txt
复制
const (

    e  = 2.71828182845904523536028747135266249775724709369995957496696763

    pi = 3.14159265358979323846264338327950288419716939937510582097494459

)

const (

  Unknown = 0

  Female = 1

  Male = 2

)

0,1,2 代表未知、女、男

如果是批量声明的常量,除了第一个外其它的常量右边的初始化表达式都可以省略,如果省略初始化表达式则表示使用前面常量的初始化表达式写法,对应的常量类型也一样的。例如:

代码语言:txt
复制
const (

    a = 1

    b

    c = 2

    d

)



fmt.Println(a, b, c, d) // "1 1 2 2"

所有常量的运算都可以在编译期完成,这样可以减少运行时的工作,也方便其他编译优化。当操作数是常量时,一些运行时的错误也可以在编译时被发现,例如整数除零、字符串索引越界、任何导致无效浮点数的操作等。

常量间的所有算术运算、逻辑运算和比较运算的结果也是常量,对常量的类型转换操作或以下函数调用都是返回常量结果:len、cap、real、imag、complex 和 unsafe.Sizeof。

因为它们的值是在编译期就确定的,因此常量可以是构成类型的一部分,例如用于指定数组类型的长度:

代码语言:txt
复制
const IPv4Len = 4



// parseIPv4 parses an IPv4 address (d.d.d.d).

func parseIPv4(s string) IP {

    var p [IPv4Len]byte

    // ...

}

如果只是简单地复制右边的常量表达式,其实并没有太实用的价值。但是它可以带来其它的特性,那就是 iota 常量生成器语法。

iota常量生成器

枚举,将变量的值一一列举出来,变量只限于列举出来的值的范围内取值。Go 语言中没有枚举这种数据类型的,但是可以使用 const 配合 iota 模式来实现。

常量声明可以使用 iota 常量生成器初始化,它用于生成一组以相似规则初始化的常量,但是不用每行都写一遍初始化表达式。在一个 const 声明语句中,在第一个声明的常量所在的行,iota 将会被置为 0,然后在每一个有常量声明的行加一。

代码语言:txt
复制
\*\*1. 普通枚举\*\*
代码语言:txt
复制
const (

    a = 0

    b = 1

    c = 2

    d = 3

)
代码语言:txt
复制
\*\*2. 自增枚举\*\*
  1. iota只能用于常量表达式
  2. 它默认开始值是0,const中每增加一行加1,同行值相同
代码语言:txt
复制
const (

    a = iota //0

    c        //1

    d        //2

)

const (

    e, f = iota, iota //e=0, f=0

    g    = iota       //g=1

)





type Weekday int



const (

    Sunday Weekday = iota

    Monday

    Tuesday

    Wednesday

    Thursday

    Friday

    Saturday

)
代码语言:txt
复制
\*\*3. 显式恢复\*\*
  1. 若中间中断iota,必须显式恢复。
代码语言:txt
复制
const (

  a = iota    //0

  b           //1

  c = 100     //100

  d           //100

  e = iota    //4

)
代码语言:txt
复制
\*\*4. 求幂次\*\*
代码语言:txt
复制
type Flags uint



const (

    FlagUp Flags = 1 << iota // is up

    FlagBroadcast            // supports broadcast access capability

    FlagLoopback             // is a loopback interface

    FlagPointToPoint         // belongs to a point-to-point link

    FlagMulticast            // supports multicast access capability

)

注:<< 表示左移的意思,即<<n==*(2^n)。

本例表示随着 iota 的递增,每个常量对应表达式 1 << iota,是连续的 2 的幂。

更复杂的例子,每个常量都是1024的幂:

代码语言:txt
复制
const (

    \_ = 1 << (10 \* iota)

    KiB // 1024

    MiB // 1048576

    GiB // 1073741824

    TiB // 1099511627776             (exceeds 1 << 32)

    PiB // 1125899906842624

    EiB // 1152921504606846976

    ZiB // 1180591620717411303424    (exceeds 1 << 64)

    YiB // 1208925819614629174706176

)

_ 实际上是一个只写变量,你不能得到它的值。这样做是因为 Go 语言中必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值。

不过 iota 常量生成规则也有其局限性。例如,它并不能用于产生 1000 的幂(KB、MB 等),因为 Go 语言并没有计算幂的运算符。

参考资料

http://shouce.jb51.net/gopl-zh/

https://github.com/datawhalechina/go-talent/blob/master/2.%E5%8F%98%E9%87%8F%E3%80%81%E5%B8%B8%E9%87%8F%E3%80%81%E6%9E%9A%E4%B8%BE.md

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 变量
    • 简短变量声明
    • 常量
    • iota常量生成器
    • 参考资料
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档