- go语言学习第三天==>函数、匿名函数与闭包、错误处理、defer关键字、painc()和recover()、type关键字
//
- 函数
func 函数名 (参数表) (返回值表)/返回值 {函数体}
demo
func example1(x int) int {
if x == 0 {
return 5
} else{
return x
}
}
//或者
func example2(x int) (int,int) {
if x == 0 {
return 1,2
} else{
return 2,2
}
return 2,22
}
函数调用
包名.函数名(参数表)
或者 同包可以不写
函数名(参数表)
example1(1)
//假设example2在包test中则
a,b:=test.example2(2)
//或者
test.example2(22222)
不定参数
func myfunc(args ...int) { //接收不定数量的int类型参数
for _, arg := range args {
fmt.Println(arg)
}
}
//调用
myfunc()
myfunc(1)
myfunc(1,2)
不定参数传递
//假设有个myfunc2(args..int)
func myfunc(args ...int) {
// 按原样传递
myfunc3(args...)
// 传递片段,实际上任意的int slice都可以传进去
myfunc3(args[1:]...)
}
任意类型不定参数
用interface{}传递任意类型数据是Go语言的惯例用法。使用interface{}仍然是类型安全的
func Printf(format string, args ...interface{}) {
// ...
}
demo
package main
import "fmt"
func MyPrintf(args ...interface{}) {
for _, arg := range args {
switch arg.(type) {
case int:
fmt.Println(arg, "is an int value.")
case string:
fmt.Println(arg, "is a string value.")
case int64:
fmt.Println(arg, "is an int64 value.")
default:
fmt.Println(arg, "is an unknown type.")
}
}
}
func main() {
var v1 int = 1
var v2 int64 = 234
var v3 string = "hello"
var v4 float32 = 1.234
MyPrintf(v1, v2, v3, v4)
}
结果为:
1 is an int value.
234 is an int64 value.
hello is a string value.
1.234 is an unknown type.
多返回值
func (file *File) Read(b []byte) (n int, err Error)
//调用
n, _ := f.Read(buf)
//
匿名函数与闭包
1匿名函数 --即没有函数名
func(a, b int, z float64) bool {
return a*b <int(z)
}
匿名函数可以直接赋值给一个变量
f := func(x, y int) int {
return x + y
}
或者直接调用
func(a int) {
fmt.Println(a)
} (6666) // 花括号后直接跟参数列表表示函数调
//输出666
闭包
go的匿名函数就是一个闭包
闭包可以包含自由变量的代码块==》即函数外部变量
j:=10
a:=func(){
j+=10 //使用了外部变量j
}
//结果j=20
价值:这些函数可以存储到变量中,作为参数传递,并且能动态创建和返回
demo 返回值为一个匿名函数的匿名函数
a := func()(func()) { //匿名函数1
var i int = 10
return func() { //匿名函数2
fmt.Printf("i, j: %d, %d\n", i, j)
}
}() //立即调用,返回匿名函数2给a
a() //执行a 即匿名函数2
//
错误处理
go语言引入了一个error接口来处理错误如下
type error interface {
Error() string
}
如果函数要返回错误把error作为返回值的最后一个(一般情况)
func Foo(param int)(n int, err error) {
// ...
}
//调用
n, err := Foo(0)
if err != nil {
// 错误处理
} else {
// 使用返回值n
}
自定义error
type PathError struct {
Op string
Path string
Err error //包装了一个error类型
}
func (e *PathError) Error() string {
return e.Op + " " + e.Path + ": " + e.Err.Error()
}
//使用:直接把错误信息包装到PathError中
func Stat(name string) (fi FileInfo, err error) {
var stat syscall.Stat_t
err = syscall.Stat(name, &stat)
if err != nil {
return nil, &PathError{"stat", name, err}
}
return fileInfoFromStat(&stat, name), nil
}
///
defer关键字
defer关键字==>延缓函数的执行
使用时在函数或者非法前加defer即可
遇到defer关键字 紧跟其后的函数会被延迟执行
直到包含该defer语句的函数执行完毕时,其后面的函数才会被执行
不论包含defer语句的函数是通过return正常结束,还是由于panic导致的异常结束。
一个函数中允许多个defer,执行顺序与声明顺序相反。
可用于打开、关闭、连接、断开连接、枷锁、释放资源
无论多复杂的的逻辑结构,资源都能被正确释放
释放资源的defer一般跟在请求资源的语句后
defer srcFile.Close()
defer dstFile.Close()
defer func() {
// 做你复杂的清理工作
} ()
///
panic()和recover函数
go语言内置了这两个函数
func panic(interface{})
func recover() interface{}
当调用panic,正常的函数执行流程将立即终止
recover()函数用于处理错误终止
defer func() {
if r := recover(); r != nil {
log.Printf("Runtime error caught: %v", r)
}
}()
type关键字
1定义结构体
type student struct{
name string
id int
}
2 定义接口
type student interface{
read()
write()
}
3类型定义
type str string //以string为基础 定义一个str类型
type getStudent func(id int)//定义一个getStudent类型的方法
4类型别名
type str= string //把string 取别名为str
类型查询
变量名.(type)
a:="im a boss"
v:=a.(type)
fmt.Println(v)
//结果为string