• Go 语言基础(三) 之 函数


    内建函数
    1、预定义了少数函数,这意味着无需引用任何包就可以使用它们
    close 用于 channel 通讯。
    delete 用于在 map 中删除实例
    len 和 cap 可用于不同的类型, len 用于返回字符串、slice 和数组的长度。
    new 用于各种类型的内存分配。
    make 用于内建类型(map、slice 和 channel)的内存分配。
    copy 用于复制 slice。
    append 用于追加 slice。
    panic 和 recover 用于异常处理机制。
    print 和 println 是底层打印函数,可以在不引入 fmt 包的情况下使用。它们 主要用于调试。
    complex、real 和 imag 全部用于处理 复数。
     
     
    可以利用 array 在列表中进行多个值的排序,或者使用更加灵活的:slice。字典
    或哈希类型同样可以使用,在 Go 中叫做 map。
    2、array
    array 由 [n]<type> 定义, n 标示 array 的长度,而 <type> 标示希望存储的内容的 类型。
    对 array 的元素赋值或索引是由方括号完成的:
    var arr [10]int
    arr[0] = 42
    arr[1] = 13
    fmt.Printf("The first element is %d ", arr[0])
    像 var arr = [10]int 这样的数组类型有固定的大小。大小是类型的一部分。由于不同的大小是不同的类型,因此不能改变大小。
    数组同样是值类型的:将一个数组赋值给另一个数组,会复制所有的元素。
     
    尤其是当向函数内传递一个数组的时候,它会获得一个数组的副本,而不是数组的指针。
    可以像这样声明一个数组:var a [3]int,如果不使用零来初始化它,
    则用复合声明:a := [3]int{1, 2, 3} 也可以简写为 a := [...]int{1, 2, 3},Go 会自动统计元素的个数。
    注意,所有项目必须都指定。因此,如果你使用多维数组,有一些内容你必须录入:
    a := [2][2]int{ [2]int{1,2}, [2]int{3,4} } 类似于:
    a := [2][2]int{ [...]int{1,2}, [...]int{3,4} }
    当声明一个 array 时,你必须在方括号内输入些内容,数字或者三个点 (...)。
     
    3、slice
    slice 与 array 接近,但是在新的元素加入的时候可以增加长度。
    slice 总是指向底层的一个 array。
    slice 是一个指向 array 的指针,这是其与 array 不同的地方;
    slice 是引用类型,这意味着当赋值某个 slice 到另外一个变量,两个引用会指向同一个 array。
     
    例如,如果一个函数需要一个 slice 参数,在其内对 slice 元素的修改也会体现在函数调用者中,
    这和传递底层的 array 指针类似。通过:
    sl := make([]int, 10)
    创建了一个保存有 10 个元素的 slice。需要注意的是底层的 array 并无不同。
    slice 总是与一个固定长度的 array 成对出现。其影响 slice 的容量和长度。
    首先创建了 m 个元素长度的 array,
    元素类型 int: var array[m]int
    然后对这个 array 创建 slice: slice := array[0:n] 然后现在有:
    • len(slice)== n ;
    • cap(slice)== m ;
    • len(array)== cap(array)== m
     
    4、map
    在 Go 中有 map 类型。map 可以认为是一个用字符串做索引的数组(在其最简单的形式下)。
    下面定义了 map 类型,用于将 string(月的缩写) 转换为 int – 那个月的天数。
    一般定义 map 的方法是:map[<from type>]<to type>
    monthdays := map[string]int{
    "Jan": 31, "Feb": 28, "Mar": 31,
    "Apr": 30, "May": 31, "Jun": 30,
    "Jul": 31, "Aug": 31, "Sep": 30,
    "Oct": 31, "Nov": 30, "Dec": 31, ← 逗号是必须的
    }
    留意,当只需要声明一个 map 的时候,使用 make 的形式:
    monthdays := make(map[string]int)
    当在 map 中索引(搜索)时,使用方括号。
    例如打印出 12 月的天数:
    fmt. Printf("%d ", monthdays["Dec"])
     
    当对 array、slice、string 或者 map 循环遍历的时候,
    range 会帮助你,每次调用,它都会返回一个键和对应的值。
     
    year := 0
    for _, days := range monthdays { ← 键没有使用,因此用 _, days
    year += days
    }
    fmt.Printf("Numbers of days in a year: %d ", year)
     
    向 map 增加元素,可以这样做:
    monthdays["Undecim"] = 30 ← 添加一个月
    monthdays["Feb"] = 29 ← 年时重写这个元素
     
    检查元素是否存在,可以使用下面的方式:
    var value int
    var present bool
    value, present = monthdays["Jan"] ← 如果存在,present 则有值 true ← 或者更接近 Go 的方式
    v, ok := monthdays["Jan"] ← “逗号 ok”形式
     
    也可以从 map 中移除元素:
    delete(monthdays, "Mar") ← 删除"Mar" 吧,总是下雨的月
    通常来说语句 delete(m, x) 会删除 map 中由 m[x] 建立的实例。
     
     
    八、函数
    1、函数是构建 Go 程序的基础部件
    type mytype int ← 新的类型,参阅第 5 章
    func (p mytype) funcname(q int) (r,s int) { return 0,0 }
     
    函数没有返回值:
    func subroutine(in int) {
    return
    }
     
    简单的将输入返回:
    func identity(in int) int {
    return in
    }
     
    递归函数:
    func rec(i int) { if i == 10 {
    return }
    rec(i+1)
    fmt.Printf("%d ", i)
    }
    这会打印:9 8 7 6 5 4 3 2 1 0。
     
    2、作用域
    定义在函数外的变量是全局的,那些定义在函数内部的变量,对于 函数来说是局部的。如果命名覆盖——一个局部变量与一个全局变量有相同的 名字——在函数执行的时候,局部变量将覆盖全局变量
     
    package main
    var a int
    func main() {
    a=5
    println(a)
    f()
    }
     
    func f() {
    a := 6
    println(a)
    g()
    }
    func g() {
    println(a)
    }
    输出内容将是:565。
    局部变量仅仅在执行定义它的函数时有效
     
     
    3、多值返回
    函数和方法可以返回多个值
    func nextInt(b []byte, i int) (int, int) {
    x := 0
    // 假设所有的都是数字
    for ; i < len(b); i++ {
    x = x*10 + int(b[i])-'0'
    }
    return x, i
    }
    你可以在输入的数组中扫描数字,像这样:
     
    a := []byte{'1', '2', '3', '4'}
    var x int
    for i := 0; i < len(a); { ← 没有 i++
    x, i = nextInt(a, i)
    println(x)
    }
     
    4、命名返回值???
     
    5、延迟代码???
    假设有一个函数,打开文件并且对其进行若干读写。在这样的函数中,经常有 提前返回的地方。如果你这样做,就需要关闭正在工作的文件描述符。
     
    defer 语句。
     
    在 defer 后指定的函数会在函数退出前调用。
    for i := 0; i < 5; i++ {
    defer fmt.Printf("%d ", i)
    }
    延迟的函数是按照后进先出(LIFO)的顺序执行,所以上面的代码打印: 4 3 2 1 0。
     
    在 defer 中访问返回值
    func f() (ret int) { ← ret 初始化为0
    defer func() {
    ret++ ← ret 增加为1
    }()
    return 0 ← 返回的是1 而不是0
    }
     
    6、变参
    接受变参的函数是有着不定数量的参数的
    func myfunc(arg ...int) {}
    arg ... int 告诉 Go 这个函数接受不定数量的参数
     
    7、函数作为值
    函数也是值
     
    匿名函数
    func main() {
    a := func() { ← 定义一个匿名函数,并且赋值给 a
    println("Hello")
    } ← 这里没有 ()
    a() ← 调用函数
    }
    如果使用 fmt.Printf("\%T ", a) 打印 a 的类型,输出结果是 func()。
     
    8、回调
     
    当函数作为值时,就可以很容易的传递到其他函数里,然后可以作为回调。
    首先定义一个函数,对整数做一些 “事情”:
    func printit(x int) { ← 函数无返回值
    fmt.Print("%v ", x) ← 仅仅打印
    }
     
    这个函数的标识是 func printit(int),或者没有函数名的:func(int)。
    创建新的函数使用这个作为回调,需要用到这个标识:
    func callback(y int, f func(int)) { ← f 将会保存函数
    f(y) ← 调用回调函数 f 输入变量 y
    }
     
     
     
  • 相关阅读:
    android studio首次运行出错
    分享4种CSS3效果(360度旋转、旋转放大、放大、移动)
    重温CSS:Border属性
    CSS3之过渡Transition
    ASP.NET(C#)--Repeater中生成“序号”列
    Android开发过程问题集锦(Continuous updating)
    ZOJ Problem Set Vol 1(Update paste)
    MapReduce基本原理及应用
    Tensorflow之基于MNIST手写识别的入门介绍[转载]
    Tensorflow 计算模型——计算图
  • 原文地址:https://www.cnblogs.com/wjq310/p/6545481.html
Copyright © 2020-2023  润新知