in function int main怎么解决 in function int main()_递归


在任何编程语言中,都必须编写优秀的代码。 优秀的代码意味着高效运行和可读性强,大部分人(尤其是程序员或开发人员)都容易理解该代码。通过函数将大部分代码拆分为较小的代码块。

Function in Go

函数是一段代码,用于执行可以重用的特定任务。


//func receiver functionName(parameters types) return type
 func (receiver)funcName(params) returnValues {
    //code
}


使用函数


//declare a function called greet
func greet() {
    fmt.Println("Hello!")
}

func main() {
    greet() //prints "Hello!"
}


我们在main函数中调用一个简单的函数greet()。


package main
import (
    "fmt"
)
//With one parameter with return value type string
func greet(s string) string {
    return fmt.Sprint("Hello ", s, "!")
}

//With two parameters with return value type boolean
func search(word string, keyword string) bool {
    return strings.Contains(word, keyword)
}

//With variadic parameter with two return values type int
func countAvg(xi ...int) (int, int) {
    total := 0
    //calculate sum of ints
    for _, v := range xi {
        total += v
    }
    //calculate average of int
    avg := total / len(xi)

    return total, avg
}

func main() {
    greetings := greet("John Doe")
    sum, avg := countAvg(1, 2, 3, 4, 5, 6)
    fmt.Println(greetings)
    fmt.Println("sum: ", sum, " average: ", avg)
    fmt.Println(search("Go is really awesome", "is"))
}


countAvg的参数称为可变参数。 可变参数是可以被多个值动态使用的参数。 可变参数必须放在函数参数声明的最后部分。


//example
func foo(s string, xi ...int) {
    //code
}
// 这是错误的示范,程序会抛出错误
func foo(xi ...int, s string) {
    //code
}


Function with receiver

声明函数时,也可以在function中声明接收者(receiver)。如果我们使用struct,那么receiver真的很有用。

在编写函数之前,让我们创建一个称为person的简单struct。


type person struct {
    name string
}


然后,创建一个名为greet()的函数,其receiver类型的称为person。


func (p person) greet() {
    fmt.Println("Hello, my name is", p.name, "!")
}


要使用此函数,必须先实例化该结构,然后调用该函数。


func main() {
    p := person{name: "Firstname"} //instantiate the struct
    p.greet()                      //call greet() from instantiated struct called p
}


匿名Function

匿名函数是没有名称的函数。


func() {
    //code
}
// using IIFE (Immediately-invoked Function Expression) style, we can declare a function that executes directly
func() {
    //code
}() // 使用这种语法会马上调用函数


匿名函数的使用:


func() {
    //calculates sum
    xi := []int{1,2,3,4,5,6}
    total := 0
    for _, v := range xi {
        total += v
    }
    fmt.Println("The sum is: ",total) // The sum is:  21
}()


Go里面的头等公民

Go中的头等公民原则也适用,但很少使用。 头等公民是指函数可用作函数中的参数或返回值。


func main() {
    //declare a function that stored inside variable called cb
    cb := func(xi ...int) int {
        total := 0
        for _, v := range xi {
            total += v
        }
        return total
    }

    //declare a slice of int
    data := []int{1, 2, 3, 4, 5, 6}
    //call foo() function with arguments:
    //1. cb means callback function
    //2. data... means retrieve all items from slice called "data"
    result := foo(cb, data...)
    fmt.Println("the result: ", result) // the result:  21
}

func foo(callback func(...int) int, xi ...int) int {
    return callback(xi...)
}


闭包

闭包是一个持有外部环境变量的函数。


//declare a function that returns a function with return value int
func increment() func() int {
    i := 0 //forms a closure
    return func() int { 
        i++ //access variable "i" from outside this function body
        return i
    }
}

func main() {
    myInt := increment()
    fmt.Println(myInt())
    fmt.Println(myInt())
    fmt.Println(myInt())

    myInt2 := increment() //this function call resets "i" value
    fmt.Println(myInt2())
}


递归

递归是一个能够自行执行功能的函数。 像计算阶乘这类问题,可以使用递归巧妙解决。


func factorial(n int) int {
    if n == 0 || n == 1 {
        return 1
    } else {
        return n * factorial(n-1) 
    }
}

func main() {
    result := factorial(5)
    fmt.Println("The result: ", result) // The result:  120
}

// 5!的计算方法:
// 5! = 5 * 4 * 3 * 2 * 1

// 使用factorial函数:
// 5! = factorial(5)
//    = 5 * factorial(4)
//    = 5 * 4 * factorial(3)
//    = 5 * 4 * 3 * factorial(2)
//    = 5 * 4 * 3 * 2 * factorial(1)
//    = 5 * 4 * 3 * 2 * 1 * factorial(0)
//    = 5 * 4 * 3 * 2 * 1 * 1
//    = 120


defer, panic and recover

在某些情况下,需要在某个时间执行函数。例如,必须在某些函数完成后执行functionA()。 基于这种情况,defer语句确实很有用。 defer是在函数完成后才执行。


//(x,y int) is shorthand version of (x int, y int)
func calculate(x, y int) int {
    return x + y
}

func main() {
    defer fmt.Println("First")
    fmt.Println(calculate(4, 5)) // 在fmt.Println(calculate(4,5))完成后执行延迟函数fmt.Println("First")。
}

// output
// 9
// First


Go中有许多错误处理机制,示例之一使用panic函数。 如果发生错误,则执行紧急处理并停止程序。


func divide(x, y int) int {
    if y == 0 { // 如果y ==0 程序发生panic
        panic("cannot divide by 0")
    } else {
        return x / y
    }
}

func main() {
    fmt.Println(divide(24, 0))
    fmt.Println("Hello") //这句不会运行
}

// output
// panic: cannot divide by 0


尽管程序出现panic,但defer仍然会执行。


func divide(x, y int) int {
    if y == 0 {
        panic("cannot divide by 0")
    } else {
        return x / y
    }
}

func main() {
    defer fmt.Println("Hello") //this is executed because this function is deferred
    fmt.Println(divide(24, 0))
}
// output
// Hello
// panic: cannot divide by 0


要恢复出现panic的程序,可以在defer函数中使用recover函数。 如果在非defer函数中使用,recover函数将变得毫无作用,因为程序处于panic状态,defer函数仍将执行。


func divide(x, y int) int {
    if y == 0 {
        panic("cannot divide by 0")
    } else {
        return x / y
    }
}

func main() {
    //declare an anonymous func to recover from panic
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered!")
        }
    }()
    fmt.Println(divide(24, 0))
}
// output
// Recovered!


divide()函数处于panic状态,但defer函数仍然执行。 执行匿名函数以从panic中恢复,最后停止程序执行。

资料来源

以下是一些有用的资源,可进一步了解Go编程语言

  • Function
  • Function Declaration
  • Function Literal
  • Closure
  • defer,panic and recover

我希望本文对帮助学习Go编程语言有所帮助。 如果您有任何想法或反馈,可以在下面的评论留言。