四时宝库

程序员的知识宝库

对比着学 Go 语言-基础:函数(go语言方法和函数)

流程语句是整个程序的逻辑依托,函数构成逻辑结构。

和 Python 一样,在 Go 中,函数的基本组成为 6 个部分:

  • func 关键字
  • 函数名
  • 参数列表
  • 返回值
  • 函数体
  • 返回语句

函数的涉及范围包括 5 个部分:

  • 函数定义
  • 函数调用
  • 不定参数
  • 多返回值
  • 匿名函数与闭包

函数定义

package mymath
import "errors"

func Add (a int, b int) (ret int, err error) {
  if a<0 || b<0 { // 假设这个函数只支持两个非负数组的加法
    err = errors.New("Should be non-negative numbers")
    return
  }
  
  return a+b, nil // 支持多重返回值
  
}

在 Python 中不需要对变量做显示的声明,在 Go 中则尽量的做到叙述的简练。如果参数列表中若干个相邻的参数类型相同,则可以在参数列表中省略前面变量的类型声明。

func Add(a, b int)(ret int, err error) {
  //...
}

如果返回值列表中多个返回值的类型相同,也可以用同样的方式合并。

func Add(a, b int) int {
 // ... 
}

函数调用

函数调用的方式包括 2 步:

  1. 导入函数所在包
  2. 直接调用
import "mymath"
c := mymath.Add(1,2)

和 Python 一样,利用函数的多重返回值和错误处理机制,Go 写出的代码也很优雅美观。

在可见性方面,对比 Python 中使用下划线来表达私有和公有的情况,Go 使用的是首字母的大小写做区分:

  • 小写字母开头的函数私有
  • 大写字母开头的函数共有

不定参数

不定参数涉及到 3 个方面:

  • 不定参数类型
  • 不定参数传递
  • 任意类型的不定参数

从不定参数类型来讲:

func myfunc(args ...int) {
 for _, arg := range args {
   fmt.Println(arg)
 }
}

args ... 表示函数接受不定数量的参数,这些参数的类型全部是 int 。

在调用时,可以如下:

myfunc(2, 3, 4)
myfunc(1, 3, 7, 13)

... type 这样的类型本质上是一个数组切片,使用中只能作为函数的最后一个参数的参数类型存在。

它带来的好处体现在调用时,避免了在调用时编写冗余的代码。

// 简化
myfunc2([]int{1, 3, 7, 13})
// 成为
myfunc(1, 3, 7, 13)

传递不定参数

func myfunc(args ...int) {
  // 按照原样传递
  myfunc3(args...)
  
  // 传递片段,实际上任意的 int slice 都可以传禁区
  myfunc3(args[1:]...)
}

描述完长度的限制,下面是类型的限制

func Printf(format string, args ...interface{}) {
  
}

Python 在不定参数方面规则少,使用优雅,Go 作为静态语言为了能够尽量跟上这种简练的用法,增加了 1 条规则:

  • 使用 interface{} 关键字
package main
import "fmt"

func MyPrintf(args ...interface{}) {
  for _, arg := range args {
    switch arg.(type) {
      case int:
      	fmt.Println(arg, "")
      case string:
        fmt.Println(arg, "")
      case int64:
        fmt.Println(arg, "is an int64 value")
      default:
        fmt.Println(arg, 'is an unkown 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)
  
}

Python 和 Go 都有多值返回。Go 中可以给返回值命名,它在函数开始的时候会被自动初始化为空。在函数中执行不带任何参数的 return 语句时,会返回对应的返回值变量的值。

n, _ := f.Read(buf)

Python 和 Go 中都存在匿名函数和闭包。

匿名函数的特点有 3 个:

  • 无函数名
  • 简短
  • 直接执行
# 匿名函数
func(a, b int, z float64) bool {
 return a*b < int(z) 
}


f := func(x, y int) int {
 return x + y 
}

func(ch chan int) {
 ch <- ACK 
}(replay_chan) // 花括号后直接跟参数列表表示函数调用

闭包的特点有 2 个:

  • 一级对象,可以存储到变量中作为参数传递给其他函数
  • 动态创建和返回

适用的应用场景有 3 个:

在下面的例子中,变量 a 指向了闭包函数,函数中引用了局部变量 i 和 j。i 被隔离,在闭包外不能被修改,改变 j 的值以后,再次调用 a,j 的结果修改成功。

package main
import (
  "fmt"
  )


func main() {
  var j int = 5
  a := func()(func()) {//前一个 func() 定义匿名函数,后一个 func() 表示返回值是一个匿名函数
    var i int = 10 // 只有内部的匿名函数才能访问 i,其他途径无法访问。
    return func() { // 里层新建的匿名函数,但是它可以使用外层匿名函数中定义的变量,整体称为闭包
      fmt.Printf("i, j: %d, %d\n", i, j)
    }
  }()
  
  a()
  
  j *= 2
  
  a()
  
  
}

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接