go 学习之函数

Posted tigerzhouv587

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go 学习之函数相关的知识,希望对你有一定的参考价值。

个人把go函数理解分三种:

1.普通函数

普通函数声明:

func name(parameter-list) (result-list)
  body

package main

import "fmt"

func add(x int, y int) int return x + y
func sub(x, y int) (z int)  z = x - y; return
func first(x int, _ int) int  return x  #_表示这个参数不会被使用
func zero(int, int) int  return 0  # 可能觉得没啥意义,这里只表示这样写是可以的

func main() 
    fmt.Printf("%T\n", add) // "func(int, int) int"
    fmt.Printf("%T\n", sub) // "func(int, int) int"
    fmt.Printf("%T\n", first) // "func(int, int) int"
    fmt.Printf("%T\n", zero) // "func(int, int) int"

2.方法

方法就是在一个函数上,加上了一层类型限制,让这个函数变成这个类型的方法。

package main

import "math"
type Point struct X, Y float64  #声明一个结构体有x,y两个float64类型的属性
// traditional function
func Distance(p, q Point) float64  #声明一个函数,接收两个Point类型的参数,返回float64类型
    return math.Hypot(q.X-p.X, q.Y-p.Y)

// same thing, but as a method of the Point type
func (p Point) Distance(q Point) float64  #声明一个Point类型的方法
    return math.Hypot(q.X-p.X, q.Y-p.Y)

func main() 
    p:=Point1,2
    q:=Point4,6
    print(Distance(p,q))
    print(p.Distance(q))

方法的特点:针对不同的类型可以有相同的方法名,同一个类型的方法名都是唯一的

如果要把一个方法赋给多个类型怎么办呢,难道是跟函数的参数一样写多个类型嘛,并不是,而是通过结构体的嵌套来实现的

package main

type dog struct 
    name string

type animal struct 
    dog
    sex string


func (d dog) sayHi() 
    print(d.name)
    print(" say hi to you!")

func main() 
    a := animalsex: "girl"
    a.name = "tom"
    b := dog"tim"
    b.sayHi()
    a.dog.sayHi()

3.匿名函数

f := func (m, n int) int  return m * n  匿名函数的结构就是如此

函数多返回值:

最常见的就是很多内置函数有两个返回值,一个返回结果,一个返回error

func addAndSub(x int,y int) (int,int) 
    return x+y,x-y

#定义在函数中的匿名函数可以访问外部函数的所有变量

函数递归:

package main
func add(x int) int   //表示0到x求和
    if x>0
        return x+add(x-1)
    else 
        return 0
    


func main() 
    println(add(5))

可变参数:

在声明可变参数函数时,需要在参数列表的最后一个参数类型之前加上省略符号“...”,这表示该函数

会接收任意数量的该类型参数

func sum(vals...int) int 
  total := 0
  for _, val := range vals 
    total += val
  
  return total

deferred 函数:

你只需要在调用普通函数或方法前加上关键字defer,就完成了defer所需要的语法。当defer语句被执行时,跟在defer后面的函数会被延迟执行。直到包含该defer语句的函数执行完毕时,defer后的函数才会被执行,不论包含defer语句的函数是通过return正常结束,还是由于panic导致的异常结束。你可以在一个函数中执行多条defer语句,它们的执行顺序与声明顺序相反。defer语句经常被用于处理成对的操作,如打开、关闭、连接、断开连接、加锁、释放锁。通过defer机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源被释放。释放资源的defer应该直接跟在请求资源的语句后。

func title(url string) error 
    resp, err := http.Get(url)
    if err != nil   //正常情况每个return 之前都需要close把
        return err
    
    defer resp.Body.Close()
    ct := resp.Header.Get("Content-Type")
    if ct != "text/html" && !strings.HasPrefix(ct, "text/html;") 
        return fmt.Errorf("%s has type %s, not text/html", url, ct)
    
    doc, err := html.Parse(resp.Body)
    if err != nil 
        return fmt.Errorf("parsing %s as HTML: %v", url, err)
    
    // ...print docs title element… 这里要有close
    return nil

Panic 异常

Go的类型系统会在编译时捕获很多错误,但有些错误只能在运行时检查,如数组访问越界、空指针引用等。这些运行时错误会引起painc异常。

不是所有的panic异常都来自运行时,直接调用内置的panic函数也会引发panic异常;panic函数接受任何值作为参数。当某些不应该发生的场景发生时,我们就应该调用pani

switch s := suit(drawCard()); s 
        case "Spades": // ...
        case "Hearts": // ...

        case "Diamonds": // ...
        case "Clubs": // ...
        default:
            panic(fmt.Sprintf("invalid suit %q", s)) // Joker?
    

虽然Go的panic机制类似于其他语言的异常,但panic的适用场景有一些不同。由于panic会引起程序的崩溃,因此panic一般用于严重错误,如程序内部的逻辑不一致。勤奋的程序员认为任何崩溃都表明代码中存在漏洞,所以对于大部分漏洞,我们应该使用Go提供的错误机制,而不是panic,尽量避免程序的崩溃。在健壮的程序中,任何可以预料到的错误,如不正确的输入、错误的配置或是失败的I/O操作都应该被优雅的处理,最好的处理方式,就是使用Go的错误机制。

 

以上是关于go 学习之函数的主要内容,如果未能解决你的问题,请参考以下文章

Scala深入学习之函数学习

python学习之函数

python学习之函数学习进阶

Python学习之函数进阶

python学习之函数学习进阶

python学习之函数学习进阶