Go语⾔的变量定义
Go语⾔中,变量的声明⽅式如下:
var identifier type
也可以选择在声明的时候,直接赋值
var identifier [type] = value
在类型定义的时候,可以省略type,Go语⾔可以⾃动推到数据类型。我们也可以同时定义多个变量,在
赋值的时候,需要注意,等号左右的数量、类型要⼀致。⽐如:
var x, y = 123, "hello"
var的定义变量⽅法没有区域限制,相⽐⽽⾔,Go开发者更喜欢另外⼀种定义变量且赋值的⽅式,那就
是⽤“:=“,“:=“必须出现函数中,这种⽅式可以⽅便的定义变量,包括接收函数返回结果,它利⽤的仍然
是Go语⾔⾃动推到类型的优势。
a := 123
str := “hello”
常量与iota
在Go语⾔当中,使⽤const关键字定义常量,所谓常量,就是在程序运⾏时,值不会被修改的标识。常
量的定义格式如下:
const identifier [type] = value
根据我们的经验,[type]这样被中括号扩起来的代表可以省略,也就是常量也可以⽀持类型它推导。同
样的,常量也可以⼀次定义多个,这⼀点与变量是相同的。来看⼀个示例:
package main
import "fmt"
func main() {
const LENGTH int = 10
const WIDTH = 5
const a, b, c = 1, false, "str" //多重赋值
//注意⽤ := ,代表定义变量area
area := LENGTH * WIDTH
//Printf与Printfln的区别是格式化以及⾃带换⾏
fmt.Printf("area is %d\n", area)
println(a, b, c)
}
结果
area is 50
1 false str
优雅的使⽤常量
在常量定义中,为了使常量的值更灵活,我们可以使⽤iota关键字,使⽤iota后,常量定义可以⾮常灵活。
//定义业务类型
const (
login = iota // iota = 0
logout
user = iota + 2 //iota = 2,user = 2+2 = 4
account = iota * 3 //iota = 3, account = 3*3 = 9
)
const (
apple, banana = iota + 1, iota + 2 // iota = 0
peach, pear //iota = 1
orange, mango //iota = 2
)
func main() {
fmt.Println(login, logout, user, account)
fmt.Println(apple, banana, peach, pear, orange, mango)
}
结果
0 1 4 9
1 2 2 3 3 4
Go语⾔的指针
在C语⾔⾥,掌握指针⼏乎可以掌握⼀切,Go语⾔中的指针并没有像C语⾔⾥那样妖魔化,指针所表达
的就是它指向变量的地址。指针背后的作⽤往往才是更关键的,那就是值传递与引⽤传递。
package main
import "fmt"
func main() {
a := 10
var b *int = &a // b指向a的地址
fmt.Println(*b) //打印的是10
*b = 100 //通过b可以修改a的值
fmt.Println(a, *b) // 此时打印的都是100
}
结果
10
100 100
如果我们想对两个变量的值进⾏互换,函数像下⾯这样写,最后得到的是失败的结果
func swap(a , b int) {
temp := a
a = b
b = temp
}
很显然值传递的⽅式不能解决变量替换的问题,通过指针是可以的
package main
import "fmt"
func main() {
a := 1
b := 2
swap2(&a,&b)
fmt.Println(a,b)
}
func swap2(a, b *int) {
temp := *a
*a = *b
*b = temp
}
结果
2 1
条件与分⽀
条件分⽀是任何语⾔必不可少的⼀部分,Go语⾔的条件分⽀语法上还真有特殊性。
package main
import "fmt"
func main() {
a := 10
if a > 10 { //左括号⼀定要写在表达式同⾏,与函数要求相同
fmt.Println("My God ,a is ", a)
} else if a < 10 {
fmt.Println("a is too small")
} else {
fmt.Println("a == ", a)
}
}
结果
a == 10
也要特别注意⼀点:Go语⾔中if后的表达式必须是bool型值,否则语法检测不通过。
package main
import "fmt"
func main() {
a := 10
if a { //左括号⼀定要写在表达式同⾏,与函数要求相同
fmt.Println("My God ,a is ", a)
}
结果
.\test.go:7:5: non-boolean condition in if statement
Go语⾔也⽀持switch,switch的好处就是可以针对某个变量可能的值进⾏分⽀匹配处
理,语法如下:
package main
import "fmt"
func main() {
var fruit string
fmt.Println("Please input a fruit's name:")
fmt.Scanf("%s", &fruit)
switch fruit {
case "banana":
fmt.Println("I want 2 banana!")
case "orange":
fmt.Println("I want 3 orange!")
case "apple":
fmt.Println("I want an apple!")
case "pear":
fmt.Println("I do not like pear!")
default:
fmt.Println("Are you kidding me?")
}
}
Go语⾔的循环
Go语⾔种循环没有while关键字,取⽽代之的都是由for来处理,for⽀持三种⽅式:
1. for init; condition; post { }
2. for condition { }
3. for {}
package main
import (
"fmt"
"time"
)
func main() {
//计算1+2+3+……+100 = ?
//第⼀种⽅式
sum := 0
i := 0
for i = 1; i <= 100; i++ {
sum += i
}
fmt.Println("sum is ", sum)
//第⼆种⽅式
i = 1
sum = 0
for i <= 100 {
sum += i
i++
}
fmt.Println("sum is ", sum)
//死循环 - 开启刷屏模式
for {
fmt.Println("heihei")
time.Sleep(time.Second * 1) //每次执⾏睡眠1s
}
}
结果
sum is 5050
sum is 5050
heihei
heihei
heihei
heihei
heihei
heihei
heihei
......
函数
函数是针对某些特定功能的封装,便于多次调⽤,函数也是语⾔当中⾮常重要的部分,Go语⾔函数的格
式如下:
func function_name( [parameter list] ) [return_types] {
函数体
}
说明:
- func 函数关键字
- function_name 函数名称
- parameter list 参数列表,根据设计需要,提供参数的顺序和类型要求,可以为空
- return_types 返回类型,⽀持0或多个返回类型,如果超过⼀个类型时,需要⽤⼩括号
- 函数体 函数的功能实现部分
package main
import (
"fmt"
)
func main() {
x,y := 10,20
//函数调⽤,同时获得2个返回值
sum, sub := add_sub(32, 21)
fmt.Println(sum, sub)
//获得函数指针,此时addsubptr相当于 func add_sub(a int, b int) (int, int)
addsubptr := add_sub
//通过函数指针的⽅式调⽤
sum1, sub1 := addsubptr(1, 2)
fmt.Println(sum1, sub1)
}
func add_sub(a int, b int) (int, int) {
return a + b, a - b
}
结果
30 -10
函数作为参数传递
package main
import (
"fmt"
)
func main() {
a := math(10, 20, add) //传⼊add函数,求和
b := math(10, 20, sub) //传⼊sub函数,求差
fmt.Println(a, b)
}
func add(a int, b int) int {
return a + b
}
func sub(a int, b int) int {
return a - b
}
//函数作为特殊的类型也可以当作参数,调⽤时要求f参数必须是 func(a, b int) int 这样类型的函
func math(a, b int, f func(a, b int) int) int {
return f(a, b)
}
匿名函数与函数闭包
有的时候,我们为了⽀持⼀个功能⽽实现⼀个函数,但是还不想给这段功能实现起⼀个名字,我们可以
定义匿名函数,Go语⾔也是借鉴了其他语⾔的特点,在语法上⽀持了匿名函数,匿名函数与后⽂介绍
Go并发相互配合,杀伤⼒巨⼤。
func(a, b int) int {
return a + b
}(3, 4)
注意上述代码为⼀个匿名函数执⾏的代码段,它与普通函数的区别是没有函数名称,并且在{}之外还有
调⽤参数传递,如果没有参数,直接放()就可以了。
由于对匿名函数的⽀持,再加上Go语⾔的函数也可以作为返回值,所以在Go语⾔中可以⽀持闭包,所
谓闭包就是能够读取其他函数内部变量的函数。
package main
import (
"fmt"
)
func getSequence() func() int {
i := 0
return func() int {
i += 1
return i
}
}
func main() {
// nextNumber 为⼀个函数,函数 i 为 0
nextNumber := getSequence()
// 调⽤ nextNumber 函数,i 变量⾃增 1 并返回
fmt.Println(nextNumber())
fmt.Println(nextNumber())
fmt.Println(nextNumber())
fmt.Println("------------------") //华丽的分割线
nextNumber1 := getSequence()
fmt.Println(nextNumber1())
fmt.Println(nextNumber1())
}
结果
1
2
3
------------------
1
2
从执⾏结果来看,nextNumber1⼜从1开始重新开始了,虽然他们函数内部变量名字都是i,但是在不同
的函数调⽤内部,i所在的内存区域也是不同的,因⽽nextNumber和nextNumber1代表的必然是不同
的序列。