美文网首页程序员
Go语言入门经典 4~6章读书笔记

Go语言入门经典 4~6章读书笔记

作者: 跑马溜溜的球 | 来源:发表于2020-06-18 15:51 被阅读0次

    第4章 函数

    4.1 函数是什么

    4.1.2 返回单个值

    func isEven(i int) bool{
        return i % 2 == 0;
    }
    

    4.1.3 返回多个值

    在Go语言中,可在函数签名中声明多个返回值,让函数返回多个结果。在这种情况下,终止语句可返回多个值。

    func getPrize()(int, string){
        i := 2
        s := "goldfish"
        
        return i,s
    }
    

    调用这个函数时,可直接将返回值赋给变量并使用它们。

    func main() {
        num, prize := getPrize();
        fmt.Println(num, prize)
    }
    

    4.2 定义不定参数函数

    不定参数函数是参数数量不确定的函数。通俗地说,这意味着它们接受可变数量的参数。在Go语言中,能够传递可变数量的参数,但它们的类型必须与函数签名指定的类型相同。要指定不定参数,可使用3个点(…)。

    在下面的示例中,函数签名指定函数可接受任意数量的int参数。

    func sumNum(nums...int) int{
    }
    

    4.3 使用具名返回值

    具名返回值让函数能够在返回前将值赋给具名变量,这有助于提升函数的可读性,使其功能更加明确。要使用具名返回值,可在函数签名的返回值部分指定变量名。

    package main
    
    import (
        "fmt"
    )
    
    func sayHi()(x string, y string){
        x = "hello"
        y = "world"
        return;
    }
    
    func main() {
        str1, str2 := sayHi();
        fmt.Println(str1)
        fmt.Println(str2)
    }
    

    4.4 使用递归函数

    要在函数中实现递归,可将调用自己的代码作为终止语句中的返回值。

    4.5 将函数作为值传递

    Go将函数视为一种类型,因此可将函数赋给变量,以后再通过变量来调用它们。

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    func anotherFunction(f func() string) string{
        return f();
    }
    
    func main() {
        fn := func() string{
            return "function called"
        }
    
        fmt.Println(reflect.TypeOf(fn));
        fmt.Println(anotherFunction(fn));
    }
    

    结果如下

    func() string
    function called
    

    函数anotherFunction的签名中包含一个子函数签名,这表明这个参数是一个返回字符串的函数。

    第5章控制流程

    5.2 使用else语句

    func main() {
        var b = false;
        if b { 
            fmt.Println("b is true")
        } else {
            fmt.Println("b is false")
        }   
    }
    
    • else不能单启一行,否则会报错。比如
    if b{
    }
    else{
    }
    
    • if判断中的b可以使用()括起来。

    5.3 使用else if语句

    func main() {
        var b int = 2;
        if (b == 1) {
            fmt.Println("b is 1")
        } else if b == 2{
            fmt.Println("b is 2")
        }
    }
    

    5.4 使用比较运算符

    关于Go语言中的比较运算符,一个要点是两个操作数的类型必须相同。例如,无法对字符串和整数进行比较。

    5.5 使用算术运算符

    算术运算符也只能用于类型相同的操作数。

    var a float32 = 1.1
    var c int = 1;
    
    fmt.Println(a + c)
    

    运行时会报错

    invalid operation: a + c (mismatched types float32 and int)
    

    5.7 使用switch语句

    func main() {
        fmt.Println("Hello, World!")
        i := 9
        switch i{
            case 2:
                fmt.Println("two")
            case 9:
                fmt.Println("nine")
            case 10:
                fmt.Println("ten")
            default:
                fmt.Println("what's wrong")
        }
    }
    

    不同于大多数语言,go的switch中没有break!

    5.8 使用for语句进行循环

    只包含条件的for语句

    func main() {
        i := 0;
        for i<10{
            i++;
            fmt.Println("i is", i)
        }
    }
    

    5.8.1 包含初始化语句和后续语句的for语句

    func main() {
        for i:=0; i<10; i++{
            fmt.Println("i is", i)
        }
    }
    

    注意,for之后的初始化及条件不能用()括号起来!

    5.8.2 包含range子句的for语句

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        numbers := []int{1,3,5,7}
        for i,n := range numbers{
            fmt.Printf("index is %d, value is %d\n", i, n)
        }
    }
    

    解读:

    • 声明变量numbers,并将一个包含4个整数的数组赋给它。
    • for语句指定了迭代变量i,用于存储索引值。这个变量将在每次迭代结束后更新。
    • for语句指定了迭代变量n,用于存储来自数组中的值。它也将在每次迭代结束后更新。

    5.9 使用defer语句

    defer能够让您在函数返回前执行另一个函数。函数在遇到return语句或到达函数末尾时返回。defer语句通常用于执行清理操作或确保操作(如网络调用)完成后再执行另一个函数。

    func main() {
        defer fmt.Println("first defer")
        defer fmt.Println("second defer")
        defer fmt.Println("third defer")
    
        fmt.Println("Hello, World!")
    }
    

    结果:

    Hello, World!
    third defer
    second defer
    first defer
    

    外部函数执行完毕后,按与defer语句出现顺序相反的顺序执行它们指定的函数。

    第6章数组、切片和映射

    6.1 使用数组

    要创建数组,可声明一个数组变量,并指定其长度和数据类型。

    var cheeses [2]string
    
    • 使用关键字var声明一个名为cheeses的变量。
    • 将一个长度为2的数组赋给这个变量。
    • 这个数组的类型为字符串。

    6.2 使用切片

    切片是底层数组中的一个连续片段,通过它您可以访问该数组中一系列带编号的元素。

    为何要使用切片?

    在Go语言中,使用数组存在一定的局限性。采用前面的数组cheeses表明方试,您无法在数组中添加元素;然而切片比数组更灵活,您可在切片中添加和删除元素,还可复制切片中的元素。可将切片视为轻量级的数组包装器,它既保留了数组的完整性,又比数组使用起来更容易。

    要声明一个长度为2的空切片,可使用如下语法。

    var cheeses = make([]string, 2)
    
    • 使用关键字var声明一个名为cheeses的变量。
    • 在等号右边,使用Go内置函数make创建一个切片,其中第一个参数为数据类型,而第二个参数为长度。在这里,创建的切片包含两个字符串元素。
    • 将切片赋给变量cheeses。

    看下面这个例子

    func main() {
        var cheeses = make([]string, 2)
        var books [2]string
        fmt.Println(reflect.TypeOf(cheeses), len(cheeses));
        fmt.Println(reflect.TypeOf(books), len(books));
    }
    

    输出

    []string 2
    [2]string 2
    
    • books为数组,cheeses为切片
    • 两者长者均为2,但TypeOf的结果是有差别的。

    6.2.1 在切片中添加元素

    Go语言提供了内置函数append,让您能够增大切片的长度。append会在必要时调整切片的长度,但它对程序员隐藏了这种复杂性。

    var books = make([]string, 2)
    books = append(books, "book3");
    

    函数append也是一个不定参数函数。这意味着使用函数append可在切片末尾添加很多值。

    var books = make([]string, 2)
    books = append(books, "b3", "b4", "b5");
    fmt.Println(books, len(books));
    

    结果

    [  b3 b4 b5] 5
    

    6.2.2 从切片中删除元素

    要从切片中删除元素,也可使用内置函数append。在下面的示例中,删除了索引1处的元素。

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        var books = make([]string, 3)
        books[0] = "b0";
        books[1] = "b1";
        books[2] = "b2";
        fmt.Println(books, len(books));
        
        var index int = 1;
        books = append(books[:index], books[index+1:]...);
        fmt.Println(books, len(books));
    }
    

    6.2.3 复制切片中的元素

    要复制切片的全部或部分元素,可使用内置函数copy。在复制切片中的元素前,必须再声明一个类型与该切片相同的切片,例如,不能将字符串切片中的元素复制到整数切片中。

    func main() {
        var books = make([]string, 3)
        books[0] = "b0";
        books[1] = "b1";
        books[2] = "b2";
        fmt.Println(books, len(books));
        
        var another = make([]string, 2)
        copy(another, books[])
        fmt.Println(another, len(another));
    }
    
    • another长度只有2,所以copy后只含b0, b1两个元素。

    函数copy在新切片中创建元素的副本,因此修改一个切片中的元素不会影响另一个切片。

    还可将单个元素或特定范围内的元素复制到新切片中。

    copy(another, books[1:])
    

    上述代码从books的第1个元素开始复制。执行后,another中的元素为b1,b2

    6.3 使用映射

    数组和切片是可通过索引值访问的元素集合,而映射是通过键来访问的无序元素编组。映射在信息查找方面的效率非常高,因为可直接通过键来检索数据。简单地说,映射可视为键-值对集合。

    只需一行代码就可声明并创建一个空映射。

    var players = make(map[string]int) 
    

    解读

    • 关键字var声明一个名为players的变量。
    • 在等号右边,使用Go语言内置函数make创建了一个映射,其键的类型为字符串,而值的类型为整数。
    • 将这个空映射赋给了变量players。

    向映射中添加元素

    func main() {
        var players = make(map[string]int) 
        players["sheep"] = 5 
        players["chicken"] = 2 
        players["mouse"] = 0
        fmt.Println(players)
    }
    

    注意:
    做为key的字串必须使用双引号括起来,如果使用单引号会报错。

    从映射中删除元素

    delete(players, "mouse")
    

    6.5 问与答

    问:该使用数组还是切片?

    答:除非确定必须使用数组,否则请使用切片。切片能够让您轻松地添加和删除元素,还无须处理内存分配问题。

    问:没有从切片中删除元素的内置函数吗?

    答:不能将delete用于切片。没有专门用于从切片中删除元素的函数,但可使用内置函数append来完成这种任务。

    相关文章

      网友评论

        本文标题:Go语言入门经典 4~6章读书笔记

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