变量的声明和初始化

1. 变量交换,类似python
2. 匿名变量用“_”
3. iota是特殊常量,可以认为是一个可以被编译器修改的常量,是go语言的常量计数器。在const关键字出现时将被重置为0,const中每新增一行常量声明将自动加1,直到下一个const关键字再次出现

package main

import "fmt"

func main() {
var name string = "wensen" // 变量声明并初始化
var age int // 变量声明
var ( // 声明多个变量
addr string = "beijing"
gender bool
id, phoneNumber, height int // 声明同类型的多个变量
)

age = 30 // 变量初始化
id = 123
weight := 50 // 短变量声明:变量声明并初始化,编译器会根据初始化类型识别变量类型
fmt.Println(name, age, addr, gender, id, phoneNumber, height, weight) // 打印并换行
fmt.Printf("%T, %T", age, weight) // 打印变量类型,不换行
fmt.Printf("id: %d, 内存地址: %p\n", id, &id)

var a int = 100
b := 200
b, a = a, b
fmt.Println(a, b)

c, d := test1()
e, _ := test2() // 此处_作为匿名变量
fmt.Println(c, d, e)

const url string = "www.baidu.com" // 定义常量
const A,B,C = 3.14, "victor", false

const (
a1 = iota // 特殊常量,iota从0开始计数
a2 = iota // iota = 1
a3 = iota // iota = 2
a4 // iota = 3,不赋值,也会自动计数
a5 // iota = 4
a6 = "victor" // a6是victor,但iota = 5
a7 // 腌也是"victor",不赋值就自动默认上一个变量的赋值,但iota = 6
a8 = iota // 但iota = 7
)
fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8)
}

func test1() (int, int) {
return 1, 2
}

func test2() (int, int) {
return 3, 4
}

基本数据类型

**由于Go语言不存在隐式类型转换,因此所有类型转换都必须显式的声明:**
> valueofTypeB = typeB(valueofTypeA)

package main

import "fmt"

func main() {
var flag bool = true //布尔型
var age int = 18 // 整型
var pai float64 = 3.14 // 浮点型
var size byte = 4 // byte=uint8,rune=uint32,int=uint64
var name string = "wensen" // 字符串
ch := 'H' // 字符,整型

fmt.Println(flag, size, ch)
fmt.Printf("%T,%d\n", age, age)
fmt.Printf("%T,%f\n", pai, pai) // 默认打印6位小数,四舍五入
fmt.Printf("%T,%.2f\n", pai, pai) // 保留2位小数
fmt.Printf("%T,%s\n", name, name) // 保留2位小数
fmt.Println("hello" + ", wensen") // 字符串拼接
fmt.Println("\"hello" + ",wensen\"") // 带转义符

a := 5 // int
b := 5.0 // float64
c := float64(a)
d := int(b)
fmt.Printf("%T\n,%T\n,%T\n,%T\n", a, b, c, d)
}

函数

defer语义:推迟,延迟。defer采用后进先出(栈)模式
但是参数会先传入,只是会延迟执行

package main

import "fmt"

func main() {
f("1")
fmt.Println("2")
defer f("3")
fmt.Println("4")
defer f("5")
f("6")
// 1, 2, 4, 6, 5, 3
fmt.Println(add(1, 2))
}

func f(str string) {
fmt.Println(str)
}

// 无参无返回
func printInfo() {
fmt.Printf("wensen")
}
// 有参无返回
func myPrint(msg string) {
fmt.Printf(msg)
}
// 有参有一个返回
func add(a, b int) int {
c := a + b
return c
}
// 有参有多个返回
func swap(x, y string) (string, string) {
return y, x
}

匿名函数没有函数名称,函数体后添加“()”执行,通常只能执行一次
Go语言支持函数式编程:
1. 将匿名函数作为另外一个函数的参数,就是回调函数
2. 将匿名函数作为另外一个函数的返回值,可以形成闭包结构
将fun1函数作为fun2函数的入参,fun2叫做高阶函数,fun1叫做回调函数
一个外层函数有内层函数,该内层函数会操作外层函数的局部变量,并且该外层函数的返回值就是这个内层函数。这个内外层函数的局部变量,统称为闭包结构。这种情况下局部变量的生命周期就会发生改变,正常局部变量会随着函数的额调用而创建,随着函数的结束而销毁。但是闭包结构中,外层函数的局部变量不会随着结束而销毁,因为内层函数还在继续使用它。
一般要避免出现闭包情况,但特殊需求需要使用闭包。

package main

import "fmt"

func main() {

func() {
fmt.Println("我是匿名函数,直接执行")
} ()
r1 := func(a, b int) int {
fmt.Println(a, b)
return a + b
} (1, 2)
fmt.Println(r1)

r2 := operator(1,2, add)
fmt.Println(r2)

r3 := operator(6,2, sub)
fmt.Println(r3)

r4 := operator(8, 4, func(a,b int,) int {
if b == 0 {
fmt.Println("除数为0")
return 0
} else {return a / b}
})
fmt.Println(r4)

r5 := incre() // 不会执行,返回的是地址
v1 := r5()
fmt.Println(v1) // 自增一次,返回1
v2 := r5()
fmt.Println(v2) // 自增二次,返回2

r6 := incre() // 此处重新命名了,原来r5的调用已经被销毁了
v3 := r6();
fmt.Println(v3) // 因为新的调用,自增一次,返回1
fmt.Println(r5()) // 原来的index还存在,没有随着r5销毁。因此返回3
fmt.Println(r6()) // 自增二次,返回2
}

// fun为一个函数,作为operator的一个参数
func operator(a, b int, fun func(int, int) int) int {
r := fun(a, b)
return r
}

func add(a, b int) int {
return a + b
}

func sub(a, b int) int {
return a - b
}

func incre() func() int {
index := 0 // 局部变量
res := func() int { // 内层的匿名函数
index++
return index
}
return res // 返回内层函数
}