package main;

import "fmt"

func main() {
	a, b, c := A(1, 2, 3);
	fmt.Println(a, b, c);

	//调用函数B,虽然传入的是一个slice,但外部变量并未改变,说明是值拷贝
	B(a, b, c);
	fmt.Println(a, b, c);
	d := []int{1, 2, 3};
	//这里传入的是一个slice,但外部变量确改变了,说明是地址拷贝。
	C(d);
	fmt.Println(d);
	e := 2;
	//这里把e的地址传递过去
	D(&e);
	fmt.Println(e);

	//函数E赋值给f
	f := E;
	f();

	//匿名函数
	g := func() {
		fmt.Println("我是匿名函数");
	};
	g();

	//使用闭包
	h := F(66);
	//两次调用都使用了66
	fmt.Println(h(66));
	fmt.Println(h(88));

	//调用G函数,defer反向调用
	G();
	H();

	//调用I函数
	I();
}

//GO函数不支持嵌套,重载和默认参数

//定义函数
//func 函数名(参数列表) (返回值) {函数体}
func A(a int, b int, c int) (int, int, int) {
	return a * 2, b * 2, c * 2;
}

//不定长变参,必须作为参数列表最后的参数
//传入的是一个slice
func B(a ...int) {
	for k := range a {
		a[k] = a[k] * 2;
	}
}

//传递slice
func C(a []int) {
	for k := range a {
		a[k] = a[k] * 2;
	}
}

//传递指针
func D(a *int) {
	*a = 6;
}

//函数也是一个类型
func E() {
	fmt.Println("func E");
}

//闭包
//返回值是一个函数
func F(a int) (func(int) int) {
	//打印a的地址
	fmt.Printf("%p\n", &a);
	return func(b int) int {
		fmt.Printf("%p\n", &a);
		return a + b;
	};
}

//defer执行方式类似其它语言中的析构函数
//在函数体执行结束后,按照调用顺序的相反顺序逐个执行
//常用于资源清理,文件关闭,解锁
func G() {
	defer fmt.Println(1);
	defer fmt.Println(2);
	defer fmt.Println(3);
}

func H() {
	for i := 0; i < 3; i++ {
		//这里用到了闭包
		defer func() {
			//这里的i作为地址的引用,引用局部变量i
			//函数体结束后,i的值就变成了3,所以打印三次3
			fmt.Println(i)
		}();
	}

	//这里的输出就跟上面的不一样,输出2,1,0
	for i := 0; i < 3; i++ {
		//这里是作为参数传递,是值的拷贝
		defer func(a int) {
			fmt.Println(a);
		}(i);
	}
}

//GO里面没有异常机制,但有panic/recover来处理错误
//panic可以在任何地方引发,但recover只在defer调用的函数中有效
func I() {
	J();
	K();
	M();
}

func J() {
	fmt.Println("fucn J");
}

func K() {
	//defer必须在panic之前,因为panic之后函数不会执行了。
	//通过recover对程序进行恢复
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("recover in func K");
		}
	}();
	panic("panic in func K");
}

func M() {
	fmt.Println("func M");
}

  

posted on 2017-05-04 11:16  怀素真  阅读(385)  评论(0编辑  收藏  举报