//函数
//函数是一段代码的封装
//Go语言函数传递的参数全部是形式参数 
//Go语言中函数的return不是原子操作,在底层是分为两步来执行
//第一步:返回值赋值
//第二步:真正的RET返回
//函数中如果有defer,那么defer执行的时机是在第一步和第二步之间
//函数中查找变量的顺序
//1.先在函数内部查找
//2.找不到就往函数的外面查找,一直找到全局

//函数的声明
//func 函数名(参数)(返回值){
//函数体
//}

//有参数有返回值
func sum(x int,y int)(ret int){
  ret=x+y
  return //可以不用在return后面加值
}
//没有参数有返回值
func f3()int{
   return 2
}
//没有参数没有返回值
func f2(){
  fmt.Println("f2")
}
//多个返回值
func f5()(int,string){
  return 1,"沙河"
}
//参数的类型简写
func f6(x,y int,z,m,n string)int{
 return x+y
 }
//可变长参数
func f7(x string,y ....int){
   fmt.Println(x)
   fmt.Println(y) //slice切片
}

func deferDemo(){
   fmt.Println("start")
   defer fmt.Println("嘿嘿嘿")//defer把它后面的语句延迟到函数即将返回的时候再执行
   defer fmt.Println("哈哈哈")
   defer fmt.Println("呵呵呵")
   fmt.Println("end")
   //打印顺序,呵呵呵,哈哈哈,嘿嘿嘿
}

func defe(){
  x:=5
  defer func(){
  x++
  }()
  return x
}//返回5

func defe2()(x int){
  defer func(){
  x++ 
  }()
  return 5
} //返回值=x为6

//函数类型

func f1(){
fmt.Println("Hello 沙河")
}

func main(){
  a:=f1
  fmt.Printf("%T\n",a)//a是涵数类型
}

func f2()int{
 return 10
}

func f3(x func()int) //有返回值类型函数做参数
func f3(x func())    //无返回值类型函数做参数
func f4(x func())func(int,int)int //返回值也是函数类型

//匿名函数
//函数内部不能定义带名字的函数
func main(){
 f1:=func(x,y int){
 fmt.Println(x+y)
 }
 f1(10,20)
 
 func(){
  fmt.Println("Hello world!")
 }
 
 func(){
  fmt.Println(x+y)
}(100,200)//只调一次,可立即执行
}

func lixiang(x int){
tmp:=func(){
  fmt.Println(x)
}
tmp()
}

//闭包
//一个函数除了引用给的参数之外,还用到了外部作用域的变量
//底层原理:
//1.函数可以作为返回值
//2。函数内部查找变量的顺序,先在自己内部找,找不到外层找
func lixiang2(x func(int,int),m,n int){
tmp:=func(){
x(m,n)//x()和m、n都来自外部
}
tmp()
}


//例题1
func makeSuffixFunc(suffix string) func(string)string{
  return func(name string)string{
     if !string.HasSuffix(name,suffix){ //判断suffix是否为name的后缀
     return name+suffix
   }
   return name
  }
}
func main(){
jpgFunc:=makeSuffixFunc(".jpg")
txtFunc:=makeSuffixFunc(".txt")
fmt.Println(jpgFunc("test"))
fmt.Println(jpgFunc("呵呵.jpg"))
fmt.Println(txtFunc("test"))
fmt.Println(jpgFunc("呵呵.txt"))
}


//例题2
func calc(base int)(func(int) int,func(int) int){
add:=func(i int)int{
base+=i
return base
}
sub:=func(i int)int{
base-=i
return base
}
return add,sub
}

func main(){
f1,f2:=calc(10)
fmt.Println(f1(1),f2(2))
}

//defer例题
func calc(index string,a,b int)int{
ret:=a+b
fmt.Println(index,a,b,ret)
return ret
}
func main(){
a:=1
b:=2
defer calc("1",a,calc("10",a,b))
a=0
defer calc("2",a,calc("20",a,b))
b=1
}
//执行顺序:
//1.defer calc("1",a,calc("10",a,b)) 延迟执行,calc("10",a,b)先执行
//2.calc("10",a,b) 即calc("10",1,2)
//3.defer calc("1",a,3)
//4.a=0
//5.defer calc("2",a,calc("20",a,b))
//6.calc("20",a,b) 即calc("20",0,2)
//7.defer calc("2",a,2)
//8.b=1
//9.calc("2",0,2)
//10.calc("1",0,3)

go语言 返回值为数组的函数 golang return_go语言 返回值为数组的函数

//异常恢复

func funcA(){
   fmt.Println("A")
}

func funcB(){
   defer func(){  //异常退出时会执行defer函数
    err:=recover() //recover尝试恢复错误,返回错误类型
    fmt.Println(err)
    fmt.Println("释放数据库连接...")
  }()
  panic("出现了严重的错误!!!") //抛出系统崩溃错误退出
  fmt.Println("B")
}

func funcC(){
fmt.Println("C")
}


func main(){
funcA()
funcB()
funcC()//没有recover不会执行该语句,有的话会执行
}
//输入

func main(){
fmt.Scanf("%s %d %s\n",&name,&age,&class)
fmt.Scanln(&name,&age,&class)
fmt.Scan(&name,&age,&class)
}
//作业:分金币
package main

import (
	"fmt"
)

var (
	coins = 50
	user  = []string{
		"Matthew", "Sarah", "Augustus", "Heidi", "Emilie", "Peter", "Giana", "Adriano", "Aaron", "Elizabeth",
	}
	distribution = make(map[string]int, len(user))
)

func dispatchCoin() (coin int) {
	for _, cur_user := range user {
		for _, i := range cur_user {
			switch i {
			case 'e', 'E':
				distribution[cur_user]++
				coins--
			case 'i', 'I':
				distribution[cur_user] += 2
				coins -= 2
			case 'o', 'O':
				distribution[cur_user] += 3
				coins -= 3
			case 'u', 'U':
				distribution[cur_user] += 4
				coins -= 4
			}
		}
	}
	return coins
}

func main() {
	left := dispatchCoin()
	fmt.Println("剩下:", left)

}