函数
func 函数名字(参数列表) (返回值列表) {}
eg:
// 没有返回值 func add() { } // 单个返回值 func add(a int, b int) int { } // 或 func add(a, b int) int { } // 多个返回值 func add(a int, b int) (int, int) { }
-
-
函数是一等公民,函数也是一种类型,一个函数可以赋值给变量
-
支持匿名函数,函数可以没有名字
-
多返回值
func add(a,b int) int { return a + b } func main() { // 将函数赋值给变量 c := add c(10, 20) // 变量调用函数 }
type add_func func(int, int) int // 定义一个函数类型 func add(a, b int) int { return a + b } // op add_func 即表示add_func的变量 func operator(op add_func, a int, b int) int { return op(a, b) } func main() { c := add sum := operator(c, 100, 200) fmt.Println(sum) }
当然,也可以不用type定义,直接写
func operator(op func(int, int) int, a, b int) int { return op(a, b) }
// 将匿名函数赋值给变量 result := func(a1, b1 int) int { return a1 + b1 } result(11, 22) // 定义时调用 result := func(a, b int) int { return a + b }(11, 22)
-
-
引用传递
无论是值传递,还是引用传递,传递给函数的都是变量的副本,不过,值传递是值的拷贝。引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决于对象的大小,对象越大,则性能越低
map、slice、chan、指针、interface默认以引用方式传递
func add(a, b int) (c int) { c = a + b return } func calc(a, b int) (sum int, avg int) { sum = a + b avg = (a + b) / 2 return }
func add(arg...int) int { // 0个或多个参数 } func add(a int, arg...int) int { // 1个或多个参数 } /* 其实arg是一个slice,我们可以通过arg[index]依次访问所有参数,通过len(arg)来判断参数的个数 */
-
-
多个defer语句,按先进后出的方式执行
-
defer语句中的变量,在defer声明时就决定了
func a() { i := 0 defer fmt.Println(i) // 这条语句是最后执行的,而且这里的i=0,不会受下面的i=10影响 i = 10 return } func f() { for i := 0; i < 5; i++ { defer fmt.Println("%d", i) // 根据先进后出的原则,打印4, 3, 2, 1 } }
func read() { file := open(filename) defer file.Close() // 文件操作 }
func read() { mc.Lock() defer mc.Unlock() // 其他操作 }
func read() { conn := openDatabase() defer conn.Close() // 其他操作 }
defer func() { if conn != nil { connn.Close() } }()