• 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
    ", add) // "func(int, int) int"
        fmt.Printf("%T
    ", sub) // "func(int, int) int"
        fmt.Printf("%T
    ", first) // "func(int, int) int"
        fmt.Printf("%T
    ", 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:=Point{1,2}
        q:=Point{4,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 := animal{sex: "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 doc's 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的错误机制。

  • 相关阅读:
    caioj 1914 & CH 0x20搜索(0x27A*)例题1:第K短路 Remmarguts'Date
    多项式的化简求法
    caioj 1715 表达式的转换
    HDU 2829 Lawrence
    山海经 (线段树)
    神奇的KMP
    浅谈zkw线段树(by Shine_hale)
    线段树补充
    浅谈线段树(by Shine_hale)
    k短路
  • 原文地址:https://www.cnblogs.com/tigerzhouv587/p/11395855.html
Copyright © 2020-2023  润新知