美文网首页
Golang 基本语法速查——变量、控制结构与函数

Golang 基本语法速查——变量、控制结构与函数

作者: rollingstarky | 来源:发表于2019-12-10 21:40 被阅读0次

    一、基本结构

    hello world 程序:

    package main
    
    import "fmt"
    
    func main(){
            fmt.Println("你好,世界")
    }
    

    直接运行:

    $ go run hello.go
    你好,世界
    

    构建可执行程序:

    $ go build hello.go
    $ ./hello
    你好,世界
    

    PS

    • Package 用于组织代码架构,类似于其他语言中的命名空间
    • 每个 go 源文件都必须属于(且只属于一个)特定的 package,一个 package 可以包含多个 go 代码文件
    • import 导入某个 package ,意味着获取了该 package 中可见对象的访问权限
    • import 导入的 package 未在后面的代码中使用会报错,no unnecessary code! 原则
    • main 函数没有任何参数且不返回任何值,它通常作为程序执行的入口

    导入多个包:

    import (
            "fmt"
            "os"
    )
    

    二、变量

    变量定义和赋值:var identifier [type] = value

    var a int
    var b bool
    var str string = "hello"
    var i = 5
    GOROOT := os.Getenv("GOROOT")
    

    PS

    • b := false 等同于 var b = false 。借助 Go 语言的类型推断可以省略类型声明
    • := 或者 var 形式的变量赋值,包含变量初始化动作。即 a = 1 表示将 1 赋值给变量 a(a 必须已经创建),a := 1 表示新建变量 a,并将 1 赋值给 a。
    • 使用未定义的变量,定义的本地变量未在后续代码中使用,新建变量的名称已存在等都会报错
    • 推荐使用 := 的形式,但只应该在函数内部使用

    三、字符串

    连接字符串,+

    s := "hel" + "lo"
    s += " world"
    fmt.Println(s)    // prints out "hello world"
    
    • 前缀匹配:strings.HasPrefix(s, prefix string) bool
    • 后缀匹配:strings.HasSuffix(s, suffix string) bool
    • 包含关系:strings.Contains(s, substr string) bool
    • 字符串替换:strings.Replace(str, old, new, n) string
    • 计算子字符串出现次数:strings.Count(s, str string) int
    • 分割字符串:strings.Split(s, sep string) []string
    • join 字符串:strings.join(sl []string, sep string) string

    示例代码:

    package main
    
    import (
            "fmt"
            "strings"
    )
    
    func main() {
            str := "The quick brown fox jumps over the lazy dog"
            sl := strings.Split(str, " ")
            fmt.Printf("Splitted in slice: %v\n", sl)
            // 字符串分割后的返回值 sl 是数组
            for _, val := range sl {
                    fmt.Printf("%s,", val)
            }
    
            fmt.Println()
            str2 := strings.Join(sl, "/")
            fmt.Printf("sl joined by / is: %s\n", str2)
    }
    // output
    // Splitted in slice: [The quick brown fox jumps over the lazy dog]
    // The,quick,brown,fox,jumps,over,the,lazy,dog,
    // sl joined by / is: The/quick/brown/fox/jumps/over/the/lazy/dog
    

    四、控制结构

    if-else

    if-else 结构语法如下:

    if condition1 {
        // do something
    } else if condition2 {
        // do something
    } else {
        // catch-all or default
    }
    

    PSelse 旁边的 }{ 不能隔行,否则无法编译通过。

    switch
    switch var1 {
    case val1:
        // do something
    case val2:
        // do something
    default:
        // catch-all or default
    }
    
    switch {
    case condition1:
        // do something
    case condition2:
        // do something
    default:
        // catch-all or default
    }
    
    switch initialization {
    case val1:
        // do something
    case val2:
        // do something
    default:
        // catch-all or default
    }
    

    示例代码:

    package main
    
    import (
        "fmt"
    )
    
    func Abs(x int) int {
        if x < 0 {
            return -x
        }
        return x
    }
    
    func main() {
        switch num := Abs(-5); {
        case num > 0:
            fmt.Println("Result is positive")
        case num < 0:
            fmt.Println("Never gonna happen")
        default:
            fmt.Println("Exact 0")
        }
    }
    // Result is positive
    
    for

    参考如下示例:

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        str := "Go is a beautiful language"
    
        for ix :=0; ix < len(str); ix ++ {
            fmt.Printf("Character on position %d is: %c \n", ix, str[ix])
        }
    
        for pos, char := range str {
            fmt.Printf("Character on position %d is: %c \n", pos, char)
        }
    }
    

    五、函数

    定义函数语法:

    func g() {
    }
    

    注意不能写成如下形式:

    func g()
    {
    }
    

    函数调用语法:pack1.Function(arg1,arg2, ... ,argn)

    Go 中的函数可以接收另一个函数作为参数,比如有下面两个函数:
    f1(a, b, c int) 接收三个参数
    f2(a, b int) (int, int, int) 有两个参数和三个返回值
    则可以这样调用:f1(f2(a, b))

    函数本身可以赋值给变量,如 add := binOp

    参数与返回值

    Go 中的函数可以接收 0 个或多个参数,返回 0 个或多个结果。
    传给函数的参数通常会有名称,但是也可以没有名称只包含类型:func f(int, int, float64)

    Go 函数的传参默认是按值传递,即实际传给函数的是参数值的复制。如调用 Function(arg1),函数 Function 收到的是 arg1 指向的值的副本,而不是 arg1 本身。
    如果需要函数操作传入的参数本身,即 Function(arg1) 操作 arg1 本体的值,则需要传入参数的指针(内存地址)。使用如下形式:Function(&arg1)

    大部分函数都需要返回值,可以是命名的也可以不命名。

    数量未知的参数

    函数的最后一个参数可以是 ...type 这样的形式,即 func myFunc(a, b, arg ...int) {} 。这表示函数可以接收相同类型的不定数量的参数。参考如下示例:

    package main
    
    import (
            "fmt"
    )
    
    func main() {
            x := Min(1, 3, 2, 0)
            fmt.Printf("The minimum is: %d\n", x)
    
            arr := []int{7, 9, 3, 5, 1}
            x = Min(arr...)
            fmt.Printf("The minimum in the array arr is: %d", x)
    }
    
    func Min(a ...int) int {
            if len(a) == 0 {
                    return 0
            }
            min := a[0]
            for _, v := range a {
                    if v < min {
                            min = v
                    }
            }
            return min
    }
    // The minimum is: 0
    // The minimum in the array arr is: 1
    
    Defer

    defer 关键字用于“延迟”执行某个函数或命令,由 defer 修饰的语句会在外部函数返回结果之后再执行。

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        fmt.Printf("In Main function at the top\n")
        defer Function2()
        fmt.Printf("In Main function at the bottom\n")
    }
    
    func Function2() {
        fmt.Printf("Function2: Deferred until the end of the calling function")
    }
    // In Main function at the top
    // In Main function at the bottom
    // Function2: Deferred until the end of the calling function% 
    

    如果 defer 语句中包含变量参数,则该参数的值在 defer 的位置已经确定。参考如下代码:

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        i := 0
        defer fmt.Println(i)
        i++
        fmt.Println("The number is:")
    }
    // The number is:
    // 0
    

    defer 修饰的 Println 函数虽然在程序执行流的最后输出 i 值。但变量 idefer 处的值为 0,因此最后输出 0 而不是执行 i++ 后的 1 。

    当代码中包含有多个 defer 语句时,这些语句会以 LIFO(后进先出,类似 stack)的顺序执行。

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        for i := 0; i < 5; i++ {
            defer fmt.Printf("%d", i)
        }
    }
    // 43210
    
    递归函数
    package main
    
    import (
        "fmt"
    )
    
    func main() {
        result := 0
        for i := 0; i <= 10; i++ {
            result = fibonacci(i)
            fmt.Printf("fibonacci(%d) is: %d\n", i, result)
        }
    }
    
    func fibonacci(n int) (res int) {
        if n <= 1 {
            res = 1
        } else {
            res = fibonacci(n-1) + fibonacci(n-2)
        }
        return
    }
    
    高阶函数

    函数作为参数

    package main
    
    import "fmt"
    
    func main() {
            callback(1, Add)
    }
    
    func Add(a, b int) {
            fmt.Printf("The sum of %d and %d is: %d\n", a, b, a+b)
    }
    
    func callback(y int, f func(int, int)) {
            f(y, 2)
    }
    // => The sum of 1 and 2 is: 3
    

    (匿名)函数赋值给变量

    package main
    
    import "fmt"
    
    func main() {
            for i := 0; i < 4; i++ {
                    g := func(i int) { fmt.Printf("%d", i) }
                    g(i)
                    fmt.Printf(" - g is of type %T and has value %v\n", g, g)
            }
    }
    // => 0 - g is of type func(int) and has value 0x4839d0
    // => 1 - g is of type func(int) and has value 0x4839d0
    // => 2 - g is of type func(int) and has value 0x4839d0
    // => 3 - g is of type func(int) and has value 0x4839d0
    

    函数作为返回值

    package main
    
    import "fmt"
    
    func main() {
            p2 := Add2()
            fmt.Printf("Call Add2 for 3 returns: %v\n", p2(3))
    
            TwoAdder := Adder(2)
            fmt.Printf("The result is: %v\n", TwoAdder(3))
    }
    
    func Add2() func(b int) int {
            return func(b int) int {
                    return b + 2
            }
    }
    
    func Adder(a int) func(b int) int {
            return func(b int) int {
                    return a + b
            }
    }
    // => Call Add2 for 3 returns: 5
    // => The result is: 5
    

    另一个版本的累加器,涉及到闭包:

    package main
    
    import "fmt"
    
    func main() {
            f := Adder()
            fmt.Print(f(1), " - ")
            fmt.Print(f(20), " - ")
            fmt.Print(f(300))
    }
    
    func Adder() func(int) int {
            var x int
            return func(delta int) int {
                    x += delta
                    return x
            }
    }
    // => 1 - 21 - 321
    

    参考资料

    The Way To Go: A Thorough Introduction To The Go Programming Language

    相关文章

      网友评论

          本文标题:Golang 基本语法速查——变量、控制结构与函数

          本文链接:https://www.haomeiwen.com/subject/nbxewctx.html