Technique/Tips

defer的使用—推迟到最后执行

  1. package main
  2. import "fmt"
  3. func func1() {
  4. fmt.Println("A")
  5. }
  6. func func2() {
  7. fmt.Println("B")
  8. }
  9. func func3() {
  10. fmt.Println("C")
  11. }
  12. func deferFunc() int {
  13. fmt.Println("defer func called")
  14. return 0
  15. }
  16. func returnFunc() int {
  17. fmt.Println("return func called")
  18. return 0
  19. }
  20. func returnAndDefer() int {
  21. defer deferFunc()
  22. return returnFunc()
  23. }
  24. func main() {
  25. //defer放在最后打印,压栈顺序导致先打印end2,再打印end1
  26. defer fmt.Println("main end1")
  27. defer fmt.Println("main end2")
  28. fmt.Println("main:hello go1")
  29. fmt.Println("main:hello go2")
  30. //打印结果倒序,因为压栈
  31. defer func1()
  32. defer func2()
  33. defer func3()
  34. //看defer和return哪个先打印,先打印return,后打印defer
  35. returnAndDefer()
  36. }

数组值传递

package main

import "fmt"

//传递数组,传的是值,只改动涉及的几个元素
func printArray(myArray [4]int) {
    for index, value := range myArray {
        fmt.Println("index=", index, "value=", value)
    }
}

func main() {
    //固定长度的数组,初始化默认每位是0
    var myArray [10]int
    myArray2 := [10]int{1, 2, 3, 4}
    myArray3 := [4]int{11, 22, 33, 44}
    //= 是赋值, := 是声明变量并赋值,系统自动推断类型,不需要关键字
    for i := 0; i < len(myArray); i++ {
        fmt.Println(myArray[i])
    }

    for index, value := range myArray2 {
        fmt.Println("index=", index, "value=", value)
    }
    //查看数据类型,不知道为什么打印不出来
    fmt.Println("myArray types = %T\n", myArray)
    fmt.Println("myArray2 types = %T\n", myArray2)
    fmt.Println("myArray3 types = %T\n", myArray3)

    //打印传递的数组
    printArray(myArray3)
}

动态数组引用传递

package main

import "fmt"

func printArray(myArray []int) {
    //引用传递
    //_,表示匿名的变量,之后不会用到名字
    for _, value := range myArray {
        fmt.Println("value=", value)
    }
    myArray[0] = 100
}

func main() {
    myArray := []int{1, 2, 3, 4} //动态数组,[]内没有长度,切片slice
    fmt.Printf("myArray type is %T\n", myArray)
    printArray(myArray)

    fmt.Println("------")
    for _, value := range myArray {
        fmt.Println("value=", value)
    }
}

四种切片声明方式

package main

import "fmt"

//四种slice切片方式
func main() {
    //方法一
    //slice1 := []int{1, 2, 3}

    //方法二:开辟三个空间,默认值是0
    var slice1 []int
    //slice1 = make([]int, 3)

    //方法三
    //var slice1 []int = make([]int, 3)

    //方法四: :=推断出slice是切片
    //slice1 := make([]int, 3)

    //slice1[0] = 100
    fmt.Println("len=%d, slice1=%v\n", len(slice1), slice1)

    //判断slice是否为空切片
    if slice1 != nil {
        fmt.Println("slice是有空间的")
    } else {
        fmt.Println("slice是空切片")
    }
}

slice切片追加与截取

package main

import "fmt"

func main() {
    var numbers = make([]int, 3, 5)
    fmt.Println("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)

    //追加元素,看容量的变化
    // 【0,0,0,1】 cap=5
    numbers = append(numbers, 1)
    // 【0,0,0,1,2】 cap=5
    numbers = append(numbers, 2)
    // 【0,0,0,1,2,3】 cap=10
    numbers = append(numbers, 3)
    fmt.Println("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)

    fmt.Println("------------")
    var numbers2 = make([]int, 3)
    numbers2 = append(numbers2, 2)
    fmt.Println("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)

    //数组拷贝
    s := []int{1, 2, 3} // [1,2,3]
    s1 := s[0:2]        //[1,2]
    fmt.Println(s1)
    s1[0] = 100
    fmt.Println(s)
    fmt.Println(s1)

    s2 := make([]int, 3) //[0,0,0]
    //s2复制了s
    copy(s2, s)
    fmt.Println(s2)
}

map的三种声明定义方式

package main

import "fmt"

func main() {
    //声明是一种map类型,key是string,value是string
    var myMap1 map[string]string
    if myMap1 == nil {
        fmt.Println("myMap是一个空map")
    }
    //在使用map前,先用make分配空间
    myMap1 = make(map[string]string, 10)
    myMap1["one"] = "java"
    myMap1["two"] = "C++"
    myMap1["three"] = "python"
    fmt.Println(myMap1)

    //第二种声明方式
    myMap2 := make(map[int]string)
    myMap2[1] = "java"
    myMap2[2] = "C++"
    myMap2[3] = "python"
    fmt.Println(myMap2)

    //第三种声明方式
    myMap3 := map[string]string{
        "one":   "php",
        "two":   "c++",
        "three": "python",
    }
    fmt.Println(myMap3)
}

Go占位符的使用

占位符 说明 举例 输出
%v 相应值的默认格式。 Printf(“%v”, people) {zhangsan}
%T 相应值的类型的Go语法表示 Printf(“%T”, people) main.Human
%d 十进制表示 Printf(“%d”, 0x12) 18

Struct的使用

package main

import "fmt"

//给int起了一个别名
type myint int

//定义一个结构体,把多种数据类型放在一起,书有两种属性,书名和作者
type Book struct {
    title string
    auth  string
}

func changeBook(book Book) {
    book.auth = "666"
}

//指针传递
func changeBook2(book *Book) {
    book.auth = ""
}

func main() {

    var a myint = 10
    fmt.Println("a=", a)
    //%d表示十进制,%T表示main.Human
    fmt.Printf("type of a =%T\n", a)

    var book1 Book
    book1.title = "Golang"
    book1.auth = "zhang3"

    fmt.Println("%v\n", book1)

    changeBook(book1)
    fmt.Println("%v\n", book1)

    //传book1的地址
    changeBook2(&book1)
    fmt.Println("%v\n", book1)
}

Go的继承

package main

import "fmt"

type Human struct {
    name string
    sex  string
}

func (this *Human) Eat() {
    fmt.Println("Human.eat...")

}

func (this *Human) Walk() {
    fmt.Println("Human.walk...")

}

//-------------------------------------
type Superman struct {
    Human //表示继承Human类的方法
    level int
}

//重定义父类的方法
func (this *Superman) Eat() {
    fmt.Println("Superman...")
}

//定义子类的新方法
func (this *Superman) Fly() {
    fmt.Println("Superman.fly()...")
}

func (this *Superman) Print() {
    fmt.Println("name=", this.name)
    fmt.Println("sex=", this.sex)
    fmt.Println("level=", this.level)
}

func main() {
    h := Human{"zhang3", "female"}
    h.Eat()
    h.Walk()

    //定义一个子类对象
    //方法一:s := Superman{Human{"li4", "female"}, 88}
    //方法二:
    var s Superman
    s.name = "Li4"
    s.sex = "male"
    s.level = 88

    s.Walk() //调用父类的方法
    s.Eat()  //调用子类的方法,子类重写了
    s.Fly()  //待用子类的方法
    s.Print()
}

多态

package main

import (
    "fmt"
)

//多态的要素
//有一个父类(有接口) ,interface接口的本质是一个指针
type AnimalIF interface {
    Sleep()
    GetColor() string //获取动物的颜色
    GetType() string  //获取动物的种类
}

//具体的子类,实现了父类的所有接口方法
type Cat struct {
    color string //猫的颜色
}

//子类cat完全实现一个接口
func (this *Cat) Sleep() {
    fmt.Println("Cat is sleep")
}
func (this *Cat) GetColor() string {
    return this.color
}
func (this *Cat) GetType() string {
    return "Cat"
}

//具体的类
type Dog struct {
    color string //猫的颜色
}

//子类dog完全实现一个接口
func (this *Dog) Sleep() {
    fmt.Println("Cat is sleep")
}
func (this *Dog) GetColor() string {
    return this.color
}
func (this *Dog) GetType() string {
    return "Dog"
}

func showAnimal(animal AnimalIF) {
    animal.Sleep() //多态
    fmt.Println("color=", animal.GetColor())
    fmt.Println("kind=", animal.GetType())
}

func main() {
    //父类类型的变量(指针)指向(引用)子类的具体数据变量

    /* var animal AnimalIF //接口的数据类型,父类指针
    animal = &Cat("Green")
    animal.Sleep() //调用cat的sleep方法,多态现象
    animal = &Dog("Yellow")
    animal.Sleep() //调用dog的sleep方法,多态现象
    */
    cat := Cat{"Green"}
    dog := Dog{"Yellow"}

    showAnimal(&cat)
    showAnimal(&dog)
}

Share

腾讯云技术实践精选集2021