a := 10
str := "mike"
//匿名函数,没有函数名字 形成一个闭包,函数定义,还没有调用
f1 := func() { //:=自动推到类型
fmt.Println("a= ", a)
fmt.Println("str = ", str)
}
f1()
//给一个函数类型起别名 这个写法不推荐
type FuncType func() //函数没有参数,内推返回值
//声明变量
var f2 FuncType
f2 = f1
f2()
//定义匿名函数,同时调用
func() {
fmt.Printf("a = %d, str = %s\n", a, str)
}() //后面的()代表此匿名函数
//带参数的匿名函数
f3 := func(i, j int) {
fmt.Printf("i = %d , j = %d\n", i, j)
}
f3(1, 2)
//定义匿名函数,同时调用
func(i, j int) {
fmt.Printf("i = %d , j = %d\n", i, j)
}(10, 20)
//匿名函数,有参有返回值
x, y := func(i, j int) (max, min int) {
if i > j {
max = i
min = j
} else {
max = j
min = i
}
return
}(10, 20)
fmt.Printf("x = %d, y = %d\n", x, y)
//闭包捕获外部变量的特点
a := 10
str := "mike"
func() {
//闭包以引用方式
a = 666
str = "go"
fmt.Printf("内部:a = %d, str = %s\n", a, str)
}() //()外部直接调用
fmt.Printf("外部:a = %d, str = %s\n", a, str) //外部同步
//内部:a = 666, str = go
// 外部:a = 666, str = go
// 函数的返回值是一个匿名函数,返回一个函数类型
func testUnKoun() func() int {
var x int //没有初始化,值为0
return func() int {
x++
return x * x //函数调用完毕 x自动释放
}
}
f := testUnKoun()
fmt.Println(f()) //1
fmt.Println(f()) //4
fmt.Println(f()) // 9
fmt.Println(f()) // 16
我们看到的声明周期不由它的作用域决定,变量x仍然隐式的存在于f中
// 无参无返回值
func MyFunc() {
a := 666
fmt.Println("a= ", a)
}
// 有参无返回值
// 参数传递,只能由实参传递给形参,不能反过来,单向传递
func MyFunc1(a int) { //定义函数,在()中定义的参数叫形参
//a = 111
fmt.Println("aa = ", a)
}
func MyFunc2(a int, b int) { //定义函数,在()中定义的参数叫形参 简单写法func MyFunc2(a,b int)
//a = 111
fmt.Printf("a= %d, b = %d \n", a, b)
}
func MyFunc3(a int, b string, c float64) {
fmt.Printf("a=%d, b = %s,c = %f\n", a, b, c)
}
// 不定参数类型 ...type 不定参数,只能放在形参中的最后一个参数
func MyFunc4(args ...int) { //传递的实参可以是0或者多个
fmt.Println("len(args) = ", len(args)) //获取用户传递参数的个数
for i := 0; i < len(args); i++ {
fmt.Printf("args[%d] = %d\n", i, args[i])
}
}
func main01() {
MyFunc()
MyFunc1(11) //实参
MyFunc2(666, 777)
MyFunc3(11, "aaa", 3.14)
MyFunc4(1, 2, 3)
}
// 固定参数一定要传参,不定参数根据需求传参 不定参数类型 ...type 不定参数,只能放在形参中的最后一个参数
func MyFunc5(a int, args ...int) { //传递的实参可以是0或者多个
}
func myFunc01(tmp ...int) {
for _, data := range tmp {
fmt.Println("data = ", data)
}
}
func myFunc02(tmp ...int) {
for _, data := range tmp {
fmt.Println("data = ", data)
}
}
// 不定参数的传递
func test(args ...int) {
//全部元素传递给myFunc01
myFunc01(args...)
fmt.Println("================")
//只想把后2个参数传递给另外一个函数使用
myFunc02(args[:2]...) //0~2(不包括数字2),触底传递过去 1 2
myFunc02(args[2:]...) //从args[2]开始(包括本身),把后面所有元素传递过去 3 4
}
// 无参有返回值 只有一个返回值
// 有返回值的函数需要通过return中断函数,通过return返回
func myfunc01() int {
return 666
}
// 给返回值起一个变量名,go推荐写法 常用写法
func myfunc02() (result int) {
//return 666
result = 666
return
}
// 多个返回值
func myfunc03() (int, int, int) {
return 1, 2, 3
}
// go官方推荐写法
func myfunc04() (a int, b int, c int) {
a, b, c = 111, 222, 333
return
}
// 有参有返回值
func MaxAndMin(a, b int) (max, min int) {
if a > b {
max = a
min = b
} else {
max = b
min = a
}
return
}
func funcb() (b int) {
b = 222
fmt.Println("funcb b = ", b)
return
}
// 普通函数的调用流程
func funca() (a int) {
a = 111
b := funcb()
fmt.Println("funca b = ", b)
//调用另外一个函数
fmt.Println("funca a = ", a)
return
}
//MyFunc5(111, 1, 2, 3)
//test(1, 2, 3, 4)
//var a int
//a = myfunc01()
//fmt.Println("a = ", a)
//b := myfunc01()
//fmt.Println("b = ", b)
//
//c := myfunc02()
//fmt.Println("c = ", c)
//
//a, b, c = myfunc03()
//fmt.Println(a, b, c)
//
//a, b, c = myfunc04()
//fmt.Println(a, b, c)
//max, min := MaxAndMin(10, 20)
//fmt.Println(max, min)
/**
main func
funcb b = 222
funca b = 222
funca a = 111
main a = 111
*/
//fmt.Println("main func")
//a := funca()
//fmt.Println("main a = ", a)
// 函数递归调用的流程
func testRecursion(a int) { //函数调用终止调用的条件,非常重要
if a == 1 {
fmt.Println("a = ", a)
return
}
//函数调用自身
testRecursion(a - 1)
fmt.Println("a = ", a)
}
// 数字累加
func InteragerSum() (sum int) {
for i := 0; i <= 100; i++ {
sum += i
}
return
}
func InteragerSum1(i int) int {
if i == 1 {
return 1
}
return i + InteragerSum1(i-1)
}
//testRecursion(3)
//var sum int
sum = InteragerSum()
//sum = InteragerSum1(100)
//fmt.Println("sum = ", sum)
回调函数
// 起别名
type funcType func(int, int) int
// 实现加法
func Add(a, b int) int {
return a + b
}
func Minus(a, b int) int {
return a - b
}
func Mul(a, b int) int {
return a * b
}
// 回调函数,函数参数是函数类型,这个函数就是回调函数
// 计算器可以进行四则运算 多态,多种形态 调用同一个接口,不同的表现,可以实现不同表现,加减乘除
func Calc(a, b int, fTest funcType) (result int) {
fmt.Println("Calc")
result = fTest(a, b) // 这个函数还没有实现
//result = Add(a,b) // Add必须定义后,才能调用
return
}
//a := Calc(1, 1, Add)
//fmt.Println("a = ", a)
// 形成了一个独立的空间
func testClouse() int {
//函数被调用时,x才分配空间,才初始化为0
var x int //没有初始化值为0
x++
return x * x //函数调用完毕 x自动释放
}
// 函数的返回值是一个匿名函数,返回一个函数类型
func testUnKoun() func() int {
var x int //没有初始化,值为0
return func() int {
x++
return x * x //函数调用完毕 x自动释放
}
}
main方法
//返回值为一个匿名函数,返回一个函数类型,通过f来调用返回的匿名函数,f来调用闭包函数
f := testUnKoun()
fmt.Println(f()) //1
fmt.Println(f()) //4
fmt.Println(f()) // 9
fmt.Println(f()) // 16
/**
defer作用,关键字defer用户延迟一个函数或者方法(或者当前所创建的匿名函数)的执行。注意
defer语句只能出现在函数或方法的内部。
*/
//defer 延迟调用 main函数结束前调用
defer fmt.Println("bbbbbbbbbb")
fmt.Println("aaaaaaaaaa")
//aaaaaaaaaa
//bbbbbbbbbb
如果一个函数中有多个defer语句,它们会以LIFO(后进先出)的顺序执行,哪怕函数或某个延迟调用发生错误,这些调用依旧会被执行。
/*
*
defer语句经常被用于处理成对的操作,如打开,关闭,连接,断开连接
加锁,释放锁。通过defer机制,不论函数逻辑多复杂,都能保证在任何执行路径下,
资源被释放。释放资源的defer应该直接跟在请求资源的语句后。
*/
func test(x int) {
sum := 100 / x
fmt.Println(sum)
}
func main() {
bbbbbbbbbbb
aaaaaaaaaaa
//defer fmt.Println("aaaaaaaaaaa")
//defer fmt.Println("bbbbbbbbbbb")
调用一个函数,导致内存出问题
//test(0) //这个会先调用
//defer fmt.Println("ccccccccccc")
//ccccccccccc
//bbbbbbbbbbb
//aaaaaaaaaaa
defer fmt.Println("aaaaaaaaaaa")
defer fmt.Println("bbbbbbbbbbb")
//调用一个函数,导致内存出问题
defer test(0) //
defer fmt.Println("ccccccccccc")
}
package main
import "fmt"
func main01() {
a := 10
b := 20
defer func() {
fmt.Println(a, b)
}()
a = 111
b = 222
fmt.Println(a, b) /// 111 222
}
func main() {
a := 10
b := 20
defer func(a, b int) {
fmt.Println(a, b)
}(a, b) // 10 20 把参数传递过去 已经先传递参数,只是没有调用
a = 111
b = 222
fmt.Println(a, b) /// 111 222
}
package main
import (
"fmt"
"os"
)
// 获取命令行参数
func main() {
//接收用户传递的参数,都是以字符串方式传递的
list := os.Args
n := len(list)
fmt.Println("n = ", n)
for i := 0; i < n; i++ {
fmt.Printf("list[%d] = %s\n", i, list[i])
}
for i, data := range list {
fmt.Printf("list[%d] = %s\n", i, data)
}
}
package main
import "fmt"
func test() {
a := 10
fmt.Println("a = ", a)
}
func main() {
//定义在{}里面的变量就是局部变量,只能在{}里面有效
// 执行执行到定义变量那句话,才开始分配空间,离开作用域自动释放
//作用域,变量起作用的范围
{
i := 10
fmt.Println("i = ", i)
}
}
package main
import "fmt"
func test() {
fmt.Println("test = ", a)
}
// 定义在函数外部的变量是全局变量 全部变量在任何地方都能使用
var a int
// a := 10 没有这样的写法
func main() {
//全局变量
a = 10
fmt.Println("a = ", a)
test()
}
package main
import "fmt"
var a byte //全局变量
func main() {
//不同作用域的同名变量
//不同作用域,允许定义同名变量
//使用变量的原则,就近原则
var a int //局部量
fmt.Printf("%T\n", a) //int
{
var a float32
fmt.Printf("2: %T\n", a) //float32
}
test()
}
func test() {
fmt.Printf("3: %T\n", a) //uint8
}
导入包
import "fmt" //1
import . "fmt" //2
import io "fmt" //给包名起别名
import(
"fmt"
"os"
)
import _ "fmt" //忽略此包
1 分文件编程(多个源文件),必须放在src目录
2 设置GOPATH环境变量
import _“fmt” _操作其实是引入该包,而不直接使用包里面的函数,而是调用了该包里面的init函数