二、变量
1 定义单个变量
func main(){
// 定义变量的第一种方法:全定义 var name type/var关键字 变量名 变量类型
// var name type = initialvalue 该语法可以声明并初始化
var age int = 10 // 变量如果声明就必须在后面使用,否则会报错
fmt.Println(age)
// 定义变量的第二种方法:类型推导 var name = initialvalue var关键字 变量名 = 值
// Go 能够自动推断具有初始值的变量的类型
var a = 50
fmt.Println(a)
fmt.Printf("%T", a) // %T 打印变量a的类型
// 定义变量的第三种方法:简略声明 var和类型都不写
// 简短声明要求 := 操作符左边的所有变量都有初始值
b:=20
fmt.Println(b)
}
2 定义多个变量
Go 能够通过一条语句声明多个变量。
// 定义多个变量var name1, name2 type = initialvalue1, initialvalue
var s1,s2 int = 10,20
fmt.Println(s1,s2)
在有些情况下,我们可能会想要在一个语句中声明不同类型的变量。其语法如下:
var (
name1 = initialvalue1,
name2 = initialvalue2
)
使用上述语法,下面的程序声明不同类型的变量。
package main
import "fmt"
func main() {
var (
name = "naveen"
age = 29
height int
)
fmt.Println("my name is", name, ", age is", age, "and height is", height)
}
3 注意
简短声明的语法要求 := 操作符的左边至少有一个变量是尚未声明的。考虑下面的程序:
package main
import "fmt"
func main() {
a, b := 20, 30 // 声明变量a和b
fmt.Println("a is", a, "b is", b)
b, c := 40, 50 // b已经声明,但c尚未声明
fmt.Println("b is", b, "c is", c)
b, c = 80, 90 // 给已经声明的变量b和c赋新值
fmt.Println("changed b is", b, "c is", c)
}
在上面程序中的第 8 行,由于 b 已经被声明,而 c 尚未声明,因此运行成功
但是如果我们运行下面的程序
package main
import "fmt"
func main() {
a, b := 20, 30 // 声明a和b
fmt.Println("a is", a, "b is", b)
a, b := 40, 50 // 错误,没有尚未声明的变量
}
变量也可以在运行时进行赋值。考虑下面的程序:
package main
import (
"fmt"
"math"
)
func main() {
a, b := 145.8, 543.8
c := math.Min(a, b)
fmt.Println("minimum value is ", c)
}
在上面的程序中,c 的值是运行过程中计算得到的,即 a 和 b 的最小值
4 常量
常量是一个简单值的标识符,在程序运行时,不会被修改的量。
常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
常量的定义格式:
const identifier [type] = value
你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型。
- 显式类型定义:
const b string = "abc" - 隐式类型定义:
const b = "abc"
多个相同类型的声明可以简写为:
const c_name1, c_name2 = value1, value2
顾名思义,常量不能再重新赋值为其他的值。因此下面的程序将不能正常工作,它将出现一个编译错误: cannot assign to a.。
package main
func main() {
const a = 55 // 允许
a = 89 // 不允许重新赋值
}
常量的值会在编译的时候确定。因为函数调用发生在运行时,所以不能将函数的返回值赋值给常量。
5 字符串常量
双引号中的任何值都是 Go 中的字符串常量。例如像 Hello World 或 Sam 等字符串在 Go 中都是常量。
无类型的字符串是常量
像 Hello World 这样的字符串常量没有任何类型。
const hello = "Hello World"
上面的例子,我们把 Hello World 分配给常量 hello。现在常量 hello 有类型吗?答案是没有。常量仍然没有类型。
那么, 下面的程序是如何将无类型的常量 Sam 赋值给变量 name 的呢?
package main
import (
"fmt"
)
func main() {
var name = "Sam"
fmt.Printf("type %T value %v", name, name)
}
答案是无类型的常量有一个与它们相关联的默认类型,并且当且仅当一行代码需要时才提供它。在声明中 var name = “Sam” , name 需要一个类型,它从字符串常量 Sam 的默认类型中获取。
有没有办法创建一个带类型的常量?答案是可以的。以下代码创建一个有类型常量。
const typedhello string = "Hello World"
上面代码中, typedhello 就是一个 string 类型的常量。
Go 是一个强类型的语言,在分配过程中混合类型是不允许的。让我们通过以下程序看看这句话是什么意思。
package main
func main() {
var defaultName = "Sam" // 允许
type myString string //type关键字定义新类型myString为string的别名
var customName myString = "Sam" // 允许
customName = defaultName // 不允许
}
在上面的代码中,我们首先创建一个变量 defaultName 并分配一个常量 Sam 。常量 Sam 的默认类型是 string ,所以在赋值后 defaultName 是 string 类型的。
下一行,我们将创建一个新类型 myString,它是 string 的别名。
然后我们创建一个 myString 的变量 customName 并且给他赋值一个常量 Sam 。因为常量 Sam 是无类型的,它可以分配给任何字符串变量。因此这个赋值是允许的,customName 的类型是 myString。
现在,我们有一个类型为 string 的变量 defaultName 和另一个类型为 myString 的变量 customName。即使我们知道这个 myString 是 string 类型的别名。Go 的类型策略不允许将一种类型的变量赋值给另一种类型的变量。因此将 defaultName 赋值给 customName 是不允许的,编译器会抛出一个错误 main.go:7:20: cannot use defaultName (type string) as type myString in assignmen。
6 iota
iota,特殊常量,可以认为是一个可以被编译器修改的常量。
iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。
iota 可以被用作枚举值:
const (
a = iota
b = iota
c = iota
)
第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1;所以 a=0, b=1, c=2 可以简写为如下形式:
const (
a = iota
b
c
)
实例:
package main
import "fmt"
func main() {
const (
a = iota //0
b //1
c //2
d = "ha" //独立值,iota += 1
e //"ha" iota += 1
f = 100 //iota +=1
g //100 iota +=1
h = iota //7,恢复计数
i //8
)
fmt.Println(a,b,c,d,e,f,g,h,i)
}
以上实例运行结果为:
0 1 2 ha ha 100 100 7 8