【Go语言】Go语言中的变量和常量

Go语言中的变量和常量

1 变量

变量相当于是对一块数据存储空间的命名,程序可以通过定义一个变量来申请一块数据存储空间,之后可以通过引用变量名来使用这块存储空间。

Go 语言是强类型静态语言,所以变量的声明与赋值方式与 PHP/Python 等动态语言相比有很大的区别。

  • **动态语言(弱类型语言)**是运行时才确定数据类型的语言,变量在使用之前无需申明类型,通常变量的值是被赋值的那个值的类型。比如Php、Asp、JavaScript、Python、Perl等等。

  • **静态语言(强类型语言)**是编译时变量的数据类型就可以确定的语言,大多数静态语言要求在使用变量之前必须生命数据类型。比如Java、C、C++、C#等。

1.1 变量声明和规则

Go 语言引入了关键字 var,并且将数据类型信息放在变量名之后,此外,变量声明语句不需要使用分号作为结束符,例如声明一个类型为 int 的变量 v1,示例如下:

Go 复制代码
var v1 int
// 也可以将若干需要声明的变量放置在一起
var (
    v1 int
    v2 string
)

Go 语言支持多种数据类型,这里先简单展示一下

Go 复制代码
var v1 int              // 整型
var v2 string           // 字符串
var v3 bool             // 布尔类型
var v4 [10]int          // 数组,数组元素类型为整型
var v5 struct (         // 结构体,成员变量 f 的类型为64位浮点型号
    f float64
)
var v6 *int             // 指针,指向整型
var v7 map[string]int   // map(字典),key为字符串类型,value为整型
var v8 func(a int) int  // 函数,参数类型为整型,返回类型为整型

变量在声明之后,系统会自动将变量值初始化为对应类型的零值,这里输出一下上面定义的变量。

如果变量名包含多个单词,Go 语言变量命名规则遵循驼峰命名法 ,即首个单词小写,每个新单词的首字母大写,如 userName,但如果你的全局变量希望能够被外部包所使用,则需要将首个单词的首字母也大写。

1.2 变量初始化

如果声明变量时想要同时对变量值进行初始化,可以通过以下这些方式:

Go 复制代码
var v1 int = 10 // 方式一,常规的初始化操作
var v2 = 10     // 方式二,此时变量类型会被编译器自动推导出来
v3 := 10        // 方式三,可以省略 var,编译器可以自动推导出v3的类型

代码测试如下:

这里注意Go语言变量声明使用的符号是:=,而不是=

变量进行初始化时,可以不必指定数据类型,这里让Go看上像是静态类型语言,但是与 PHP/Python/JavaScript 等动态语言不同的是,这个推导是在编译期做的,而不是运行时,因此 Go 语言还是不折不扣的静态语言。

另外,出现在 := 运算符左侧的变量应该是未声明过的,否则会导致编译错误,比如下面这个写法:

Go 复制代码
var i int
i := 2

会出现如下的报错

1.3 变量赋值与多重赋值

在 Go 语言中,变量初始化和变量赋值是两个不同的概念,变量初始化及变量声明和赋值为一条语句,变量赋值则是先声明变量,再对其进行赋值,初始化只能执行一次,赋值则可以执行多次,下面是变量赋值过程:

Go 复制代码
// 变量赋值
var v10 int 
v10 = 123
// 多重赋值
i,j = j,i

代码测试:

1.4 匿名变量

我们在使用传统的强类型语言编程时,经常会出现这种情况,即在调用函数时为了获取一个值,却因为该函数返回多个值而不得不定义一堆没用的变量。

匿名变量语法:

Go 复制代码
func GetName() (userName, nickName string) {
    return "南歌", "EuanSu"
}
​
func AnonymousVariables() {
    // 匿名变量
    // GetName返回两个值,分别是username和nickName,
    // 其中nickName是string类型,而GetName()函数中没有使用nickName,
    // 此时nickName就是一个匿名变量,它不占用命名空间,不会分配内存,
    // 因此不会产生任何开销。
    _, nickName := GetName()
    fmt.Printf("nickName value is %s\n", nickName)
}
1.5 变量的作用域

每个变量在程序中都有一定的作用范围,称之为作用域。如果一个变量在函数体外声明,则被认为是全局变量,可以在整个包甚至外部包(变量名以大写字母开头)使用,不管你声明在哪个源文件里或在哪个源文件里调用该变量。在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,函数的参数和返回值变量也是局部变量。

尽管变量的标识符必须是唯一的,但你可以在某个代码块的内层代码块中使用相同名称的变量,此时外部的同名变量将会暂时隐藏(结束内部代码块的执行后隐藏的外部同名变量又会出现,而内部同名变量则被释放),任何的操作都只会影响内部代码块的局部变量。

2 常量

在 Go 语言中,常量是指编译期间就已知且不可改变的值,常量只可以是数值类型(包括整型、 浮点型和复数类型)、布尔类型、字符串类型等标量类型。Go 语言中,我们可以通过 const 关键字来定义常量(遵循 C 语言的约定)。

2.1 常量的定义

通过 const 关键字定义常量时,可以指定常量类型,也可以省略(编译时会自动推导),常见的常量定义方式如下:

Go 复制代码
const Pi float64 = 3.14159265358979323846 
const zero = 0.0 // 无类型浮点常量 
const (          // 通过一个 const 关键字定义多个常量,和 var 类似
    size int64 = 1024
    eof = -1  // 无类型整型常量 
) 
const u, v float32 = 0, 3  // u = 0.0, v = 3.0,常量的多重赋值 
const a, b, c = 3, 4, "foo" // a = 3, b = 4, c = "foo", 无类型整型和字符串常量

代码执行测试:

由于常量的赋值是编译时期执行的,因此赋值的操作中不能出现任何需要运行才能得到结果的函数,例如如下语句就会导致编译错误:

Go 复制代码
func GetNumber() int {
    return 100
}
const num = GetNumber()
2.2 预定义常量

GO语言预定义了常量:true、false 和 iota。

iota 比较特殊,认为是一个能够被编译器修改的常量,每一个 const 关键字出现时被重置为 0,每出现一次 iota,其所代表的数字就会自动加1.

Go 复制代码
const (    // iota 被重置为 0
    c0 = iota   // c0 = 0
    c1 = iota   // c1 = 1
    c2 = iota   // c2 = 2
)
const (
    u = iota * 2;  // u = 0
    v = iota * 2;  // v = 2
    w = iota * 2;  // w = 4
)
const x = iota;  // x = 0
const y = iota;  // y = 0

代码运行测试:

如果两个 const 的赋值语句的表达式是一样的,那么还可以省略后一个赋值表达式。因此,上面的前两个 const 语句可简写为:

Go 复制代码
const ( 
    c0 = iota 
    c1 
    c2 
)
const ( 
    u = iota * 2 
    v 
    w 
)

代码运行测试:

2.3 枚举

此外,常量还可以用于枚举。

枚举中包含了一系列相关的常量,比如下面关于一个星期中每天的定义。Go 语言并不支持其他语言用于表示枚举的 enum 关键字,而是通过在 const 后跟一对圆括号定义一组常量的方式来实现枚举。

下面是一个常规的 Go 语言枚举表示法,其中定义了一系列整型常量:

Go 复制代码
const (
    Sunday = iota 
    Monday 
    Tuesday 
    Wednesday 
    Thursday 
    Friday 
    Saturday 
    numberOfDays
)

代码运行测试:

2.4 常量的作用域

和函数体外声明的变量一样,以大写字母开头的常量在包外可见(类似于 public 修饰的类属性),比如上面介绍的 PiSunday 等,而以小写字母开头的常量只能在包内访问(类似于通过 protected 修饰的类属性),比如 zeronumberOfDays 等。

函数体内声明的常量只能在函数体内生效。

相关推荐
JaguarJack4 分钟前
PHP 现代特性速查 写出更简洁安全的代码(中篇)
后端·php
echoyu.5 分钟前
java源代码、字节码、jvm、jit、aot的关系
java·开发语言·jvm·八股
Victor3561 小时前
Redis(104)Redis的最大数据量是多少?
后端
Victor3561 小时前
Redis(105)Redis的数据类型支持哪些操作?
后端
麦麦大数据1 小时前
MacOS 安装Python 3.13【同时保留旧版本】
开发语言·python·macos·python安装
上去我就QWER3 小时前
Qt中如何获取系统版本信息
开发语言·qt
我是苏苏4 小时前
C#高级:程序查询写法性能优化提升策略(附带Gzip算法示例)
开发语言·算法·c#
木木子99994 小时前
业务架构、应用架构、数据架构、技术架构
java·开发语言·架构
鬼火儿8 小时前
SpringBoot】Spring Boot 项目的打包配置
java·后端
cr7xin8 小时前
缓存三大问题及解决方案
redis·后端·缓存