### 函数参数 - 实际参数:函数实际调用时传入的参数 - 形式参数:把参数列表中的参数 ![](https://blog-heysq-1255479807.cos.ap-beijing.myqcloud.com/blog/wiki/go/function.jpg) ### 传参 - 函数参数传递采用是值传递的方式 - 所谓“值传递”,就是将实际参数在内存中的表示逐位拷贝(Bitwise Copy)到形式参数中 - 对于像整型、数组、结构体这类类型,它们的内存表示就是它们自身的数据内容,因此当这些类型作为实参类型时,值传递拷贝的就是它们自身,传递的开销也与它们自身的大小成正比 - 像 string、切片、map 这些类型它们的内存表示对应的是它们数据内容的“描述符”。当这些类型作为实参类型时,值传递拷贝的也是它们数据内容的“描述符”,不包括数据内容本身,所以这些类型传递的开销是固定的,与数据内容大小无关 ### 函数传参例外 - 对于类型为接口类型的形参,Go 编译器会把传递的实参赋值给对应的接口类型形参 - 对于为变长参数的形参,Go 编译器会将零个或多个实参按一定形式转换为对应的变长形参 - 变长参数实际上是通过切片来实现 ### Go函数特征 - 多个可以命名的返回值 - 函数可以存储在变量中 - 支持在函数内创建并通过返回值返回 - 可以作为参数传入函数 - 拥有自己的类型`type HandlerFunc func(ResponseWriter, *Request)` ### 函数健壮性原则 - 不要相信任何外部输入的参数 - 不要忽略任何一个错误 - 不要假定异常不会发生 ### defer 获取调用函数方法名 - runtime.Caller,参数为0时,返回调用者本身的信息(Trace的信息),为1是返回调用调用者的信息(调用Trace的信息) - Caller 函数有四个返回值: - 第一个返回值代表的是程序计数(pc) - 第二个和第三个参数代表对应函数所在的源文件名以及所在行数 - 最后一个参数代表是否能成功获取这些信息 - runtime.FuncForPC 函数和程序计数器(PC)得到被跟踪函数的函数信息 ```go // trace1/trace.go func Trace() func() { pc, _, _, ok := runtime.Caller(1) if !ok { panic("not found caller") } fn := runtime.FuncForPC(pc) name := fn.Name() println("enter:", name) return func() { println("exit:", name) } } func main() { defer Trace()() foo() } ```