Go 语言是强类型静态语言,它的类型转换是强制型的。

变量

变量声明和命名规则

命名规则

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

关键字 var

对于纯粹的变量声明,Go 语言引入了关键字 var,并且将类型信息放在变量名之后,此外,变量声明语句不需要使用分号作为结束符,接下来我们声明一个 name 变量,并把类型声明为 string 示例如下:

//使用关键字 var , 定义为string类型
var name string
// var 也可以将若干个需要声明的变量放置在一起,避免了重复声明var
var (
	name string
	age  int
)

变量在声明之后,系统会自动将变量值初始化为对应类型的零值,我们打印上述的2个变量,看看其默认值:

name:
age:0

变量初始化

变量只能初始化一次,我们在声明变量时可以初始化赋值,初始化赋值可以不用定义类型,变量类型会自动和右侧值类型相同

:= 是变量声明的语法糖 可以看到使用 :=可以简洁的声明一个变量并初始化, :=不能声明一个已经被声明过的变量,否则会导致编译错误 no new variables on left side of :=

在Go语言中,变量定义可以不指定变量类型,当不指定变量类型时,变量类型会自动和右侧值类型相同。

var (
	name = "青玄"
	age  = 18
)

gender := "male"

变量作用域

每个变量在程序中都有一定的作用范围,称之为作用域

如果一个变量在函数体外声明,则被认为是全局变量,可以在整个包甚至外部包(变量名以大写字母开头)使用,不管你声明在哪个源文件里或在哪个源文件里调用该变量。

在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,函数的参数和返回值变量也是局部变量。

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

package main

import "fmt"

var name = "Tony" //包内变量,只能使用var声明

func main() {
        //函数内声明的变量如果与包变量同名
	fmt.Print(name) //Tony
	variables()     //Tony
        name := "Amy"
        fmt.Print(name) //Amy
}

func variables() { 
        // 使用了包内变量
	fmt.Print(name)
}

变量赋值

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

age := 18
age = 19

Go 语言中还提供了多重赋值功能,除了可以同时声明多个变量外,还可以让我们很方便的交换变量的值

a,b := 1,3
a,b = b,a

//结果
a=3,b=1

匿名变量

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

在 Go 语言中,这种情况可以通过结合使用多重赋值和匿名变量来避免这种丑陋的写法,让代码看起来更加优雅,多重赋值上面已经介绍过,匿名变量则通过下划线 _ 来声明,任何赋予它的值都会被丢弃。

我们来看个例子,假设 GetName() 函数的定义如下,它返回两个值,分别为 userName 和 nickName

func GetName() (userName string, nickName string) {
	return "Chris", "青玄"
}

若只想获得 nickName,则函数调用语句可以用如下方式实现:

_, nickName := GetName()

常量

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

自定义常量

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

const Pi float64 = 3.14159265358979323846 //浮点型64位
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 语言预定义了这些常量:truefalse 和 iota

前面两个熟悉其他语言的应该都很熟悉,是布尔类型的真假值,iota 比较特殊,可以被认为是一个可被编译器修改的常量,在每一个 const 关键字出现时被重置为 0,然后在下一个 const 出现之前,每出现一次 iota,其所代表的数字会自动增 1。

从以下的例子可以基本理解 iota 的用法:

package main

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 语句可简写为:

const ( 
    c0 = iota 
    c1 
    c2 
)

const ( 
    u = iota * 2 
    v 
    w 
)

枚举

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

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

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

const (
    Sunday = iota 
    Monday 
    Tuesday 
    Wednesday 
    Thursday 
    Friday 
    Saturday 
    numberOfDays
)

常量的作用域

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

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