Go-基础篇-函数使用

函数使用

函数是Go语言里面的核心设计,它通过关键字func来声明,它的格式如下。

1. 函数声明

func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) {
   //这里是处理逻辑代码

   //返回多个值 

   return value1, value2
 }
  • 关键字func用来声明一个函数funcName。
  • 函数可以有一个或者多个参数,每个参数后面带有类型,通过“,”分隔函数可以返回多个值。

  • 返回值声明了两个变量output1和output2,如果你不想声明也可以,就保留两个类型声明。

  • 如果只有一个返回值且不声明返回值变量,那么你可以省略“包括返回值”的括号

  • 如果没有返回值,就直接省略最后的返回信息。

  • 如果有返回值,那么必须在函数的外层添加return语句。

2. 接收变参的函数

func funcName(input ...type) (output1 type1, output2 type2) {
   //这里是处理逻辑代码

   //返回多个值 

   return output1 type1, output2 type2
 }

注意,这些参数的类型全部是type。在函数体中,变量input是一个type的slice。

  • 使用示例
package main

import "fmt"

func main() {
   result := joinStr("h", "e", "l", "l", "o")
   fmt.Println(result) // hello
}

func joinStr(input ...string) (strRes string) {
   for _, v := range input {
      strRes += v
   }
   return
}

3. 参数传递

Go 默认使用按值传递参数,也就是传递参数的副本。函数接收参数副本之后,在使用变量的过程中可能对副本的值进行更改,但不会影响到原来的变量。如果想要影响到原来的变量,则需要传指针。需要注意的是:切片(slice)、字典(map)、接口(interface)、通道(channel)这样的引用类型都是默认使用引用传递(即使没有显示的指出指针)

3.1 按值传递使用示例

package main

import "fmt"

func main() {
   str := "good morning"
   updateStr(str)
   fmt.Println(str) // good morning
}
func updateStr(str string) string {
   str = "good evening"
   return str
}

3.2 按引用使用示例

package main

import "fmt"

func main() {
   str := "good morning"
   updateStr(&str)
   fmt.Println(str)  // good evening
}
func updateStr(str *string) string {
   *str = "good evening"
   return *str
}

4.延迟语句(defer)的使用

Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句。当函数执行到最后时,这些 defer 语句会按照逆序执行,最后该函数返回。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题。

4.1 使用示例

package main

import (
    "fmt"
    "os"
    "io/ioutil"
)

func main() {
    filePath := "/Users/liuqh/Desktop/test.json"
    str := openFile(filePath)
    fmt.Println(str) 
    //输出以下内容
    //defer 被调用了
    //文件里的内容
}

func openFile(filePath string) string {
    //打开文件
    file, err := os.Open(filePath)
    if err != nil {
        fmt.Println("open file err")
    }
    //利用defer 关闭文件
    defer testDefer(file)
    content, err := ioutil.ReadAll(file)
    if err != nil {
        fmt.Println("read file err")
    }
    return string(content)
}

func testDefer(file *os.File) {
    fmt.Println("defer 被调用了")
    file.Close()
}

4.2 函数中使用多个defer

如果有一个函数中有多个地方调用defer,那么defer采用后进先出(逆序执行)

package main

import (
    "fmt"
)

func main() {
    testDefer() // 5 4 3 2 1
}

func testDefer() {
    for i := 1; i < 6; i++ {
        defer fmt.Println(i)
    }
}

5.函数作为值、类型

在Go语言中函数也是一种变量,我们可以通过type来定义它,它的类型就是所有拥有相同的参数,相同的返回值。

type typeName func(input1 inputType1,input2 inputType2[,...])(result1 resultType1 [, ...])

5.1 使用示例

package main

import "fmt"

type testInt func(int) bool

func main() {
    numSlice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
    odd := filter(numSlice, isOdd)
    event := filter(numSlice, isEvent)
    fmt.Println(odd) // [2 4 6 8]
    fmt.Println(event) // [1 3 5 7 9]
}

func isOdd(num int) bool {
    if num%2 == 0 {
        return true
    }
    return false
}

func isEvent(num int) bool {
    if num%2 == 0 {
        return false
    }
    return true
}

func filter(arg []int, funcName testInt) []int {
    var result []int
    for _, v := range arg {
        if funcName(v) {
            result = append(result, v)
        }
    }
    return result
}

6.匿名函数

既没有名称的函数

6.1 使用示例

package main

import "fmt"

func main()  {
    f := func(a,b int) int{
        i := a + b
        return i
    }
    fmt.Println(f(1,4)) // 5 
}

转载请注明来源,欢迎指出任何有错误或不够清晰的表达。

文章标题:Go-基础篇-函数使用

文章字数:1.1k

本文作者:猿码记

发布时间:2018-04-08 11:31

原始链接:liuqh.icu/2018/04/08/Go-3.函数使用/

版权声明: 转载请保留原文链接及作者。

目录
×

看您心情~~