Go 专栏 | 变量和常量的声明与赋值

简介: 上篇文章介绍了环境搭建,并完成了学习 Go 的第一个程序 Hello World。这篇文章继续学习 Go 的基础知识,来看看变量,常量的声明与赋值。

QQ图片20220423130851.png


上篇文章介绍了环境搭建,并完成了学习 Go 的第一个程序 Hello World。这篇文章继续学习 Go 的基础知识,来看看变量,常量的声明与赋值。


本文所有代码基于 go1.16.6 编写。


变量


Go 编程的命名风格更习惯使用「短名称」和「驼峰式」的名称,而且大小写敏感。

开头必须是字母或者下划线,而且首字母是大写还是小写也是有特殊含义的。大写字母开头可以被包外引用,小写字母开头只能在包内使用,这个会在以后的文章中继续分享。


声明


第一种使用关键字 var 声明变量:


var name type = expression
复制代码


和 C 语言正好相反,类型是跟在变量名后面的。说实话,刚开始写 Go 代码的时候还真有些不习惯。


类型和表达式可以省略一个,但不能都省略。如果类型省略,则类型由初始化表达式决定;如果表达式省略,则初始化值为对应类型的零值。


对于数字是 0,布尔值是 false,字符串是 "",接口和引用(slice,指针,map,通道,函数)是 nil,对于数组或结构体这样的复合类型,零值是其所有元素或成员的零值。


// 没有初始值,会赋默认零值
var v1 int
var v2 string
var v3 bool
var v4 [10]int // 数组
var v5 []int   // 数组切片
var v6 struct {
  e int
}
var v7 *int           // 指针
var v8 map[string]int // map,key 为 string 类型,value 为 int 类型
var v9 func(e int) int
fmt.Println(v1, v2, v3, v4, v5, v6, v7, v8, v9)
// 输出
// 0  false [0 0 0 0 0 0 0 0 0 0] [] {0} <nil> map[] <nil>
复制代码


所以在 Go 中是不存在未初始化的变量的。

声明单个变量:


// 声明单个变量
var a = "initial"
fmt.Println(a)
// 声明布尔值变量
var d = true
fmt.Println(d)
复制代码


一次声明多个变量:


// 声明多个变量
var b, c int = 1, 2
fmt.Println(b, c)
复制代码


建议以组方式一次声明多个变量:


// 以组的方式声明多个变量
var (
  b1, c1 int
  b2, c2 = 3, 4
)
fmt.Println(b1, c1)
fmt.Println(b2, c2)
复制代码


第二种方式是短变量声明:


name := expression
复制代码


使用 := 来声明,Go 编译器会自动推断变量类型。注意 :== 的区别,前者是声明并赋值,后者是赋值。


这种初始化方式非常方便,在局部变量的声明和初始化时经常使用。


举个例子:


// 短变量声明方式
f := "short"
fmt.Println(f)
复制代码


多个变量:


// 声明赋值多个变量
g, h := 5, "alwaysbeta"
fmt.Println(g, h)
复制代码


有一点需要注意,多个变量声明时,最少有一个新变量,否则会报错。


var i int
// i := 100 // 报错 no new variables on left side of :=
i, j := 100, 101 // 有新值 j,不报错
fmt.Println(i, j)
复制代码


第三种使用内置 new 函数:


p := new(T)
复制代码


初始化为类型 T 的零值,并返回其地址。


先说一下如何获取变量的地址,其实很简单,使用取地址符 & 即可。


声明一个整型的变量,然后对其取地址:


// 指针
k := 6
l := &k         // l 为整型指针,指向 k
fmt.Println(*l) // 输出 6
*l = 7
fmt.Println(k) // 输出 7
复制代码


使用 new 函数声明变量:


// 使用内置函数 new 声明
var p = new(int)
fmt.Println(*p) // 输出整型默认值 0
*p = 8
fmt.Println(*p) // 输出 8
复制代码


再来看一个例子,下面两个函数是等价的,唯一的区别就是使用 new 少声明了一个中间变量。


func newInt() *int {
  return new(int)
}
func newInt1() *int {
  var p int
  return &p
}
复制代码


赋值


使用 = 来赋值:


举例:


// 变量赋值
var m, n int
m = 9
n = 10
fmt.Println(m, n)
复制代码


多重赋值:


// 变量赋值
var m, n int
m = 9
n = 10
m, n = n, m
fmt.Println(m, n)
复制代码


这个特性真是很爽,想想在 C 语言中是不能这么做的,要实现相同的效果,必须要借助一个中间变量才行。


如果有不需要的变量,使用空标识符 _ 来忽略,在 Go 语言中,如果声明了变量而不使用,程序是会报错的。


// 空标识符
r := [5]int{1, 2, 3, 4, 5}
for _, v := range r {
  // fmt.Println(i, v)
  // fmt.Println(v) // 定义 i 但不用会报错 i declared but not used
  fmt.Println(v) // 忽略索引
}
复制代码


作用域


变量分为全局变量和局部变量,局部变量会覆盖全局变量:


// 全局变量
var gg = "global"
func main() {
    // 作用域
  fmt.Println(gg) // 输出 global
  gg = "local"
  fmt.Println(gg) // 输出 local
}
复制代码


使用流程控制语句时,需要特殊注意变量的作用域:


// 条件分支下的作用域
if f, err := os.Open("./00_hello.go"); err != nil {
  fmt.Println(err)
}
f.Close() // 报错 f.Close undefined (type string has no field or method Close)
复制代码


正确的写法:


// 正确写法
file, err := os.Open("00_hello.go")
if err != nil {
  fmt.Println(err)
}
file.Close()
复制代码


常量


常量表示在程序运行过程中恒定不变的值。


声明


使用关键字 const 来声明,语法和变量类似。


一般在给常量起名的时候,会起一个有明确含义的名字。


const Pi float64 = 3.14159265358979323846
复制代码


声明单个常量:


// 无类型整型常量
const n = 500000000
// 用编译阶段即可计算出值的表达式来赋值
const d = 3e20 / n
fmt.Println(d)
// 无类型浮点常量
const zero = 0.0
复制代码


声明多个常量


// 无类型整型和字符串常量
const a, b, c = 3, 4, "foo"
fmt.Println(a, b, c)
// 多个常量
const (
  size int64 = 1024
  eof        = -1 // 无类型整型常量
)
fmt.Println(size, eof)
复制代码


iota


常量声明还有可以使用常量生成器 iota,它不会显示写出常量的值,而是从 0 开始,逐项加 1。


// 从 0 值开始,逐项加 1
const (
  a0 = iota // 0
  a1 = iota // 1
  a2 = iota // 2
)
fmt.Println(a0, a1, a2)
// 简写,表达式相同,可以省略后面的
const (
  b0 = iota // 0
  b1        // 1
  b2        // 2
)
fmt.Println(b0, b1, b2)
const (
  b         = iota      // 0
  c float32 = iota * 10 // 10
  d         = iota      // 2
)
fmt.Println(b, c, d)
复制代码


iota 在每个 const 开头被重置为 0。


// iota 在每个 const 开头被重置为 0
const x = iota // 0
fmt.Println(x)
// 同上
const y = iota // 0
fmt.Println(y)
复制代码


还可以用来作为枚举类型,比如一周 7 天,每天用一个数字表示,那么可以这么声明:


// 枚举
const (
  Sunday    = iota // 0
  Monday           // 1
  Tuesday          // 2
  Wednesday        // 3
  Thursday         // 4
  Friday           // 5
  Saturday         // 6
)
fmt.Println(Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday)
复制代码


总结


本文主要介绍了变量和常量的声明和赋值,变量声明主要有三种方式:


  1. 使用关键字 var 来声明;
  2. 使用 := 的短变量声明方式;
  3. 使用内置函数 new


其中短变量方式在声明局部变量时经常使用,而且还要注意不要和赋值 = 弄混。


常量声明和变量类似,只需要把 var 换成 const 即可。


常量还有一种特殊的声明方式,使用 iota。它不会显示写出常量的值,而是从 0 开始,逐项加 1。


变量的作用域分为全局变量和局部变量,局部变量可以覆盖全局变量,使用时需要注意。




文章中的脑图和源码都上传到了 GitHub,有需要的同学可自行下载。

地址:github.com/yongxinz/go…

目录
相关文章
初识go变量,使用var和:=来声明变量,声明变量的三种方式
这篇文章介绍了Go语言中使用`var`和`:=`声明变量的三种不同方式,包括声明单个或多个变量、通过值确定数据类型以及在函数体内使用`:=`声明局部变量。
初识go变量,使用var和:=来声明变量,声明变量的三种方式
|
1月前
|
存储 编译器 Go
go语言中的变量、常量、数据类型
【11月更文挑战第3天】
32 9
|
1月前
|
Go
go语言的复数常量
【10月更文挑战第21天】
44 6
|
1月前
|
Go
go语言的浮点型常量
【10月更文挑战第21天】
26 4
|
1月前
|
编译器 Go
go语言的整型常量
【10月更文挑战第21天】
34 3
|
1月前
|
Go
go语言常量的类型
【10月更文挑战第20天】
26 2
|
1月前
|
Go
go语言定义常量
【10月更文挑战第20天】
25 2
|
1月前
|
Go
go语言使用常量和编译时常量表达式
【10月更文挑战第19天】
29 2
|
3月前
|
安全 Go C语言
Go常量的定义和使用const,const特性“隐式重复前一个表达式”,以及iota枚举常量的使用
这篇文章介绍了Go语言中使用`const`定义常量的方法,包括常量的特性“隐式重复前一个表达式”,以及如何使用`iota`实现枚举常量的功能。
|
4月前
|
安全 Go