目录
Go语言的变量与常量
变量
什么是变量?
变量是赋予内存位置以存储特定类型的值的名称。你可以把变量理解为一个盒子,可以在里面放任何东西。在 Go 中声明变量语法方法如下:
变量声明
- 变量声明的基本语法
在 Go 语言中通常我们使用关键字var
来声明变量,格式:var 变量名 类型
,且Go采用的是后置类型的声明方式。例如:
package main
import "fmt"
func main() {
var name string // 表示声明一个名为name的string类型的变量。
name = "gotribe.cn" //赋值
fmt.Println("My name is", name)
}
该语句var name string
声明了一个名为int
类型的变量name
,上面程序输出如下:
My name is gotribe.cn
变量赋值
我们可以将变量分配给其类型的任何值。
- 声明并赋值,例如:
var age int = 18 // 表示声明一个名为 age 的整数变量,并且附上初始值为 18
var age = 18 // 隐式声明,效果同上。
多变量声明
- 多个变量同时声明,采用
var
加括号批量声明的方式 :
var (
age int = 18
name string = "Jiujiu"
)
类型推断
- 如果变量具有初始值,Go 将自动能够使用该初始值推断该变量的类型。因此,如果变量具有初始值,则
type
可以删除变量声明中的 。
var age = 29 // 类型推断为 int
fmt.Println("My age is", age)
简短声明
- 变量在声明的时候如果有初始值,我们可以使用
:=
的简短声明方式,例如:
var age, name := 17, "abc"
但是值的注意的是,简写声明需要赋值左侧的所有变量的初始值。下面的程序将打印一个错误assignment mismatch: 2 variables but 1 values
。这是因为年龄没有被赋值。
package main
import "fmt"
func main() {
name, age := "naveen" //error
fmt.Println("my name is", name, "age is", age)
}
由于 Go 是强类型的,因此声明为属于一种类型的变量不能被赋予另一种类型的值。下面的程序将打印一个错误cannot use "naveen" (type string) as type int in assignment
,因为age
它被声明为类型int
,但我们却尝试为它赋string
类型的一个值。
package main
func main() {
age := 29 // age 是 int 类型
age = "naveen" // 赋值 string 类型就会报错
}
常量
什么是常量?
常量和变量刚好相反,常量一旦声明,其值不可改变。
声明常量
- 常量声明基本的语法
常量使用关键字const
定义,用于存储不会改变的数据。常量的定义格式:const 常量名 [类型] = value
。例如:
package main
import (
"fmt"
)
func main() {
const PI = 3.14159
fmt.Println(PI)
}
在上面的代码PI
中是一个常量,它被赋值3.14159
。上面运行结果:
3.14159
声明一组常量
还有另一种语法可以使用单个语句定义一组常量。例如:
package main
import (
"fmt"
)
func main() {
const (
name = "gotribe.cn"
age = 1
country = "bejing"
)
fmt.Println(name)
fmt.Println(age)
fmt.Println(country)
}
在上面的程序中,我们声明了 3 个常量name
,age
和country
。上面的程序打印,
gotribe.cn 50 bejing
注意事项
顾名思义,常量不能再次重新分配给任何其他值。在下面的程序中,我们试图设a
为89. 这是不允许的,因为a
它是一个常量。该程序将无法运行,编译错误。
package main
func main() {
const a = 55 //声明常量并给定值
a = 89 // 这里将会报错
}
- 常量是指值不能改变的定义,它必须满足如下规则:
- 定义的时候,必须指定值
- 指定的值类型主要有三类: 布尔,数字,字符串, 其中数字类型包含(rune, integer, floating-point, complex), 它们都属于基本数据类型。
- 不能使用
:=
Go语言基础数据类型
数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,这样就可以充分利用内存。
以下是 Go 中可用的基本类型:
- bool (布尔)
- 数值类型
- int8、int16、int32、int64、int
- uint8、uint16、uint32、uint64、uint
- float32, float64
- complex64, complex128
- byte
- rune
- string
布尔类型
一般我们用于判断条件, 它的取值范围为 true
, false
, 声明如下:
// 短类型声明
var isExit := true
// 或
var isExit bool = false
字符串类型
字符串是 Go 中字节的集合。声明如下:
var say = "hello" //单行字符串
var tag = "\"" // 转义符
var say = `hello` //原样输出
var mLine = `line1 //多行输出
line2
line3
`
var str = "hello, 世界"
还有一些可以对字符串执行的操作。我们将在单独的教程中查看这些内容。
数字类型
数字类型主要分为有符号数和无符号数,有符号数可以用来表示负数,除此之外它们还有位数的区别,不同的位数代表它们实际存储占用空间,以及取值的范围。
var (
a uint8 = 1
b int8 = 1
)
具体范围
uint8 the set of all unsigned 8-bit integers (0 to 255)
uint16 the set of all unsigned 16-bit integers (0 to 65535)
uint32 the set of all unsigned 32-bit integers (0 to 4294967295)
uint64 the set of all unsigned 64-bit integers (0 to 18446744073709551615)
int8 the set of all signed 8-bit integers (-128 to 127)
int16 the set of all signed 16-bit integers (-32768 to 32767)
int32 the set of all signed 32-bit integers (-2147483648 to 2147483647)
int64 the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)
float32 the set of all IEEE-754 32-bit floating-point numbers
float64 the set of all IEEE-754 64-bit floating-point numbers
complex64 the set of all complex numbers with float32 real and imaginary parts
complex128 the set of all complex numbers with float64 real and imaginary parts
类型转换
Go 对显式类型非常严格。没有自动类型提升或转换。让我们通过一个例子来看看这意味着什么。
package main
import (
"fmt"
)
func main() {
i := 55 //int
j := 67.8 //float64
sum := i + j //int + float64 not allowed
fmt.Println(sum)
}
上面的代码在 C 语言中是完全合法的。但是在 go 的情况下,这是行不通的。i 是 int 类型,j 是 float64 类型。我们正在尝试添加 2 个不同类型的数字,这是不允许的。当你运行程序时,你会得到./prog.go:10:11: invalid operation: i + j (mismatched types int and float64)
要修复错误,i和j应该是相同的类型。让我们将j转换为 int。T(v) 是将值 v 转换为类型 T 的语法
package main
import (
"fmt"
)
func main() {
i := 55 //int
j := 67.8 //float64
sum := i + int(j) //j is converted to int
fmt.Println(sum)
}
现在,当您运行上述程序时,您可以看到122
输出。
赋值也是如此。需要显式类型转换才能将一种类型的变量分配给另一种类型。这在以下程序中进行了解释。
package main
import (
"fmt"
)
func main() {
i := 10
var j float64 = float64(i) //this statement will not work without explicit conversion
fmt.Println("j", j)
}
在第9行,i转换为float64然后赋值给j。如果不进行类型转换,当您尝试将 i 分配给 j 时,编译器将抛出错误。
循环与条件判断
在编写 Go 程序的时候,我们不仅会用前面学到的数据结构来存储数据,还会用到 if
、switch
、for
来进行条件判断和流程控制,今天我们就来一起学习下它们。
for
循环语句用于重复执行一段代码。for
是 Go 中唯一可用的循环。Go 没有其他语言(如 C)中存在的 while 或 do while 循环。
for initialisation; condition; post {
}
初始化语句将只执行一次。循环初始化后,将检查条件。如果条件评估为真,则将执行内部循环的主体{ }
,然后执行 post 语句。post 语句将在循环的每次成功迭代后执行。post语句执行后,条件会被重新检查。如果为真,循环将继续执行,否则 for 循环终止。
在 Go 中,初始化、条件和发布这三个组件都是可选的。让我们看一个例子来更好地理解 for 循环。
让我们编写一个程序,使用 for 循环打印从 1 到 10 的所有数字。
package main
import (
"fmt"
)
func main() {
for i := 1; i <= 10; i++ {
fmt.Printf(" %d",i)
}
}
在上面的程序中,i
被初始化为 1。条件语句将检查 if i <= 10
。如果条件为真,则打印 i
的值,否则终止循环。post 语句在每次迭代结束时将i
递增 1。一旦i
大于 10,循环终止。
上面的程序将打印1 2 3 4 5 6 7 8 9 10
在 for 循环中声明的变量仅在循环范围内可用。因此i
不能在 for 循环体之外访问。
break语句
该break
语句用于在 for 循环完成正常执行之前突然终止 for 循环,并将控件移动到 for 循环之后的代码行。
让我们编写一个程序,使用 break 打印从 1 到 5 的数字。
package main
import (
"fmt"
)
func main() {
for i := 1; i <= 10; i++ {
if i > 5 {
break // 如果 i > 5 就跳出
}
fmt.Printf("%d ", i)
}
fmt.Printf("\nline after for loop")
}
在上面的程序中,每次迭代都会检查 i 的值。如果 i 大于 5 则break
执行并终止循环。然后执行 for 循环之后的 print 语句。上面的程序会输出,
1 2 3 4 5
line after for loop
continue
该continue
语句用于跳过 for 循环的当前迭代。在 continue 语句之后出现在 for 循环中的所有代码都不会在当前迭代中执行。循环将继续进行下一次迭代。
让我们编写一个程序,使用 continue 打印从 1 到 10 的所有奇数。
package main
import (
"fmt"
)
func main() {
for i := 1; i <= 10; i++ {
if i%2 == 0 {
continue
}
fmt.Printf("%d ", i)
}
}
在上面的程序中,该行if i%2 == 0
检查 i 除以 2 的余数是否为 0。如果为零,则数字为偶数,continue
执行语句,控制移至循环的下一次迭代。因此,将不会调用 continue 之后的 print 语句,并且循环继续进行下一次迭代。上述程序的输出是1 3 5 7 9
注意:
break
会结束所有循环。continue
会跳过当前循环直接进入下一次循环。
if else 语句
if
是一个具有布尔条件的语句,如果该条件的计算结果为真 ,它将执行一段代码true。如果条件评估为 ,它会执行一个备用的 else 块false。在本教程中,我们将了解使用 if
语句的各种语法和方法。
if
是一个具有布尔条件的语句,如果该条件为真,则执行第一个代码块。如果条件求值为false
,则执行另一个else
块。在本教程中,我们将学习if
语句的各种语法和使用方法。
if
主要用于条件判断,语法为:
if 条件 {
# 业务代码
}
先看一个简单例子:
package main
import "fmt"
func main() {
age := 7
if age > 6 {
fmt.Println("good")
}
}
在上面的程序中,第8行age > 6
为条件,求age
是否大于 6。如果是,将打印good
文本并且返回程序。
我们可以在条件中使用 &
或 ||
来进行组合判断:
package main
import "fmt"
func main() {
age := 7
if age > 6 && age <= 12 {
fmt.Println("It's primary school")
}
}
我们还可以使用 if
…else if
…else
来实现多分支的条件判断:
package main
import "fmt"
func main() {
age := 13
if age > 6 && age <= 12 {
fmt.Println("It's primary school")
} else if age > 12 && age <= 15 {
fmt.Println("It's middle school")
} else {
fmt.Println("It's high school")
}
}
Go 的使用习惯
我们已经看到了各种if-else结构,实际上我们也看到了编写相同程序的多种方法。例如,我们已经看到了使用不同的if else
构造来编写程序来检查数字是偶数还是奇数的多种方法。哪一种是Go中惯用的编码方式?在Go的哲学中,最好避免不必要的代码分支和缩进。人们也认为,越早返回越好。提供了下面前一节的程序:
package main
import (
"fmt"
)
func main() {
if num := 10; num % 2 == 0 { //checks if number is even
fmt.Println(num,"is even")
} else {
fmt.Println(num,"is odd")
}
}
在 Go 的哲学中,编写上述程序的惯用方法是避免使用else
语句,并从if
语句返回条件为真
package main
import (
"fmt"
)
func main() {
num := 10;
if num%2 == 0 { //checks if number is even
fmt.Println(num, "is even")
return
}
fmt.Println(num, "is odd")
}
switch
switch 是一个条件语句,它计算表达式并将其与可能匹配的列表进行比较并执行相应的代码块。它可以被认为是替换复杂if else
从句的惯用方式。 例如:
package main
import "fmt"
func main() {
age := 10
switch age {
case 5:
fmt.Println("The age is 5")
case 7:
fmt.Println("The age is 7")
case 10:
fmt.Println("The age is 10")
default:
fmt.Println("The age is unkown")
}
}
注意:在 Go 中 switch
只要匹配中了就会中止剩余的匹配项,这和 Java
很大不一样,它需要使用 break
来主动跳出。
switch
的 case
条件可以是多个值,例如:
package main
import "fmt"
func main() {
age := 7
switch age {
case 7, 8, 9, 10, 11, 12:
fmt.Println("It's primary school")
case 13, 14, 15:
fmt.Println("It's middle school")
case 16, 17, 18:
fmt.Println("It's high school")
default:
fmt.Println("The age is unkown")
}
}
注意: 同一个 case 中的多值不能重复。
switch
还可以使用 if..else
作为 case
条件,例如:
package main
import "fmt"
func main() {
age := 7
switch {
case age >= 6 && age <= 12:
fmt.Println("It's primary school")
case age >= 13 && age <= 15:
fmt.Println("It's middle school")
case age >= 16 && age <= 18:
fmt.Println("It's high school")
default:
fmt.Println("The age is unkown")
}
}
小技巧: 使用 switch
对 interface{}
进行断言,例如:
package main
import "fmt"
func checkType(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("%v is an in\n", v)
case string:
fmt.Printf("%v is a string\n", v)
default:
fmt.Printf("%v's type is unkown\n", v)
}
}
func main() {
checkType(8)
checkType("hello, world")
}