目录
函数的定义
package main // 固定
import "fmt"
// func声明函数
// MyFunc为函数名
// a, b, c int为参数和参数的类型
// int声明函数的返回类型
func MyFunc(a, b, c int) int {
return a + b + c
}
func main() { // 大括号的位置是固定的
sum:=MyFunc(1, 2, 3)
fmt.Println(sum)
}
函数返回多个值
package main // 固定
import "fmt"
// func声明函数
// MyFunc为函数名
// a, b, c int为参数和参数的类型
// int声明函数的返回类型
func MyFunc() (string, int) {
name := "zeng"
age := 21
return name, age
}
func main() { // 大括号的位置是固定的
name,age:=MyFunc()
fmt.Println(name, age)
}
可变参数函数
package main // 固定
import "fmt"
func MyFunc(first int, others ...int) {
for _,value := range others {
fmt.Println(value)
}
}
func main() { // 大括号的位置是固定的
MyFunc(1, 2, 3, 4, 5)
}
函数参数的引用传递
如果形参不使用引用做为传递,那么在函数里面对形参所做的修改不会改变外部的参数
package main // 固定
import "fmt"
// 在函数内部修改name的值,是会改变外部参数的
func MyFunc(name *string) {
*name = "zeng"
}
func main() { // 大括号的位置是固定的
name:="zengraoli"
fmt.Println(name)
MyFunc(&name)
fmt.Println(name)
}
函数作为值
package main // 固定
import "fmt"
func main() { // 大括号的位置是固定的
GetName := func() string{return "zeng"}
fmt.Println(GetName())
}
匿名函数
匿名函数是指没有定义名字符号的函数,和一般函数最大的曲边是可在函数内部定义匿名函数,形成类型嵌套效果。
匿名函数的优越性在于可以直接使用函数内的变量,不必申明。
package main // 固定
import "fmt"
// 闭包需要拆包才能知道他的函数意思
func GetName() func() int{
i:=99
return func() int {
return i
}
}
func main() { // 大括号的位置是固定的
MyName:=GetName()
fmt.Println(MyName())
}
另外的例子
package main
import "fmt"
func Test(f func()) {
f()
}
func RetureTest() func(int, int) int {
return func(x int, y int) int {
return x + y
}
}
func TestStruct() {
type calc struct {
mul func(x, y int) int
}
x := calc {
func(x, y int) int {
return x * y
},
}
fmt.Println(x.mul(2, 3))
}
func TestChannel() {
c := make(chan func(int, int) int, 2)
c <- func(x int, y int) int {
return x + y
}
fmt.Println((<-c)(1, 2))
}
func main() {
// 直接执行匿名函数
func(s string) {
fmt.Println(s)
}("zengraoli1")
// 赋值给变量
add1 := func(x, y int) int {
return x + y
}
fmt.Println(add1(1, 2))
// 作为参数
Test(func() {
fmt.Println("zengraoli2")
})
// 作为返回值
add3 := RetureTest()
fmt.Println(add3(1, 88))
// 普通函数和匿名函数都可以作为结构体,或经通道传递
TestStruct()
TestChannel()
}
延迟函数defer
语法上,一个defer语句就是一个普通的函数或方法调用,在调用之前加上关键字defer。defer不影响普通的return语句,但即便执行return语句,defer也会被执行。Defer语句没有限制使用次数,执行的时候以调用defer语句顺序的倒序进行。
示例如下,首先会输出return,然后再输出close
package main // 固定
import (
"os"
"fmt"
)
func MyClose(file *os.File) {
file.Close()
fmt.Println("MyClose...")
}
func Test() {
file,err := os.OpenFile("output.txt", os.O_CREATE|os.O_APPEND, os.ModePerm|os.ModeTemporary)
if err != nil {
fmt.Println(err)
}
// 延迟关闭文件
defer MyClose(file)
out := ""
for index := 0; index < 10; index++ {
out = fmt.Sprintf("%d\r\n", index)
file.Write([]byte(out))
}
fmt.Println("return...")
}
func main() { // 大括号的位置是固定的
Test()
}
如果在return前出现错误,程序被中断了,也还是能执行defer(Go出现中断使用panic)
package main // 固定
import (
"os"
"fmt"
)
func MyClose(file *os.File) {
file.Close()
fmt.Println("MyClose...")
}
func Test() {
file,err := os.OpenFile("output.txt", os.O_CREATE|os.O_APPEND, os.ModePerm|os.ModeTemporary)
if err != nil {
fmt.Println(err)
}
// 延迟关闭文件
defer MyClose(file)
out := ""
for index := 0; index < 10; index++ {
out = fmt.Sprintf("%d\r\n", index)
file.Write([]byte(out))
if index == 3 {
panic("抛出异常后,程序就要终止了.")
}
}
fmt.Println("return...")
}
func main() { // 大括号的位置是固定的
Test()
}
可以看到正常的return输出已经没有了,但依然还能看到Close的输出,说明defer还是会继续执行
还有一个其他作用,能够利用defer来做异常捕获,参看
https://blog.csdn.net/qq_27682041/article/details/78786689
错误处理
Go的错误处理方式比较复古,返回一个error,比如下面的
package main
import (
"fmt"
"errors"
)
func div(x, y int) (int, error) {
if y == 0 {
return 0, errors.New("division by zeor")
}
return x / y, nil
}
func main() {
z, err := div(5, 0)
if err != nil {
fmt.Println(err)
}
fmt.Println(z)
}
还可以自定义错误类型,以容纳更多上下文状态信息,还可以基于类型做出判断
package main
import "fmt"
type DivError struct {
x, y int
}
func (DivError) Error() string {
return "division by zeor"
}
func div(x, y int) (int, error) {
if y == 0 {
return 0, DivError{x, y}
}
return x / y, nil
}
func main() {
z, err := div(5, 0)
if err != nil {
switch e := err.(type) {
case DivError:
fmt.Println(e, e.x, e.y)
default:
fmt.Println(e)
}
}
fmt.Println(z)
}
*panic和recover
panic和recover的用法更接近于try/catch结构,除非是不可恢复性、导致系统无法正常工作的错误,否则不建议使用panic
使用可以参考
https://www.cnblogs.com/sunshine-anycall/p/4746066.html