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