Go语言基础:Interface接口、Goroutines线程、Channels通道详细案例教程

一、Interface

1. Declaring and implementing an interface

        package main

        import "fmt"

        type VowelsFinder interface {
    
    
            FindVowels() []rune
        }

        type MyString string

        func (ms MyString) FindVowels() []rune {
    
    
            var vowels []rune
            for _, rune := range ms {
    
    
                if rune == 'a' || rune == 'e' || rune == 'i' || rune == 'o' || rune == 'u' {
    
    
                    vowels = append(vowels, rune)
                }
            }
            return vowels
        }

        func main() {
    
    
            name := MyString("LiangXiaoQing")
            var v VowelsFinder
            v = name
            fmt.Printf("vowels are %c", v.FindVowels())
        }

        // vowels are [i a i a o i]

2. Practical use of an interface

        type SalaryCalculator interface {
    
    
            CalculateSalary() int
        }
        type Permanent struct {
    
    
            empId    int
            basicapy int
            pf       int
        }

        type Contract struct {
    
    
            empId    int
            basicapy int
        }

        type Freelancer struct {
    
    
            empId       int
            ratePerHour int
            totalHours  int
        }

        func (p Permanent) CalculateSalary() int {
    
    
            return p.basicapy + p.pf
        }

        func (c Contract) CalculateSalary() int {
    
    
            return c.basicapy
        }

        func (f Freelancer) CalculateSalary() int {
    
    
            return f.ratePerHour * f.totalHours
        }

        func totalExpense(s []SalaryCalculator) {
    
    
            expense := 0
            for _, v := range s {
    
    
                expense = expense + v.CalculateSalary()		// 循环添加每个值
            }
            fmt.Printf("Total Expense Per Month $%d", expense)
        }

        func main() {
    
    
            p1 := Permanent{
    
    
                empId:    1,
                basicapy: 4999,
                pf:       10,
            }

            p2 := Permanent{
    
    
                empId:    2,
                basicapy: 5999,
                pf:       20,
            }

            c1 := Contract{
    
    
                empId:    3,
                basicapy: 3000,
            }

            f1 := Freelancer{
    
    
                empId:       4,
                ratePerHour: 77,
                totalHours:  666,
            }

            f2 := Freelancer{
    
    
                empId:       5,
                ratePerHour: 66,
                totalHours:  111,
            }
            employees := []SalaryCalculator{
    
    p1, p2, c1, f1, f2}
            fmt.Println(employees)
            totalExpense(employees)
        }

        // [{1 4999 10} {2 5999 20} {3 3000} {4 77 666} {5 66 111}]
        // Total Expense Per Month $72636

3. Nterface internal representation

        type Worker interface {
    
    
            Work()
        }

        type Person struct {
    
    
            name string
        }

        func (p Person) Work() {
    
    
            fmt.Println(p.name, "is Working")
        }

        func describe(w Worker) {
    
    
            fmt.Printf("Interface type %T value %v\n", w, w)
        }

        func main() {
    
    
            p := Person{
    
    
                name: "Like",
            }
            var w Worker = p

            describe(w)
            w.Work()
        }

        // Interface type main.Person value {Like}
        // Like is Working

4. Empty interface

        func describe(i interface{
    
    }) {
    
    
            fmt.Printf("type = %T, value= %v\n", i, i)
        }

        func main() {
    
    
            s := "Hello World"
            describe(s)
            i := 55
            describe(i)
            strt := struct {
    
    
                name string
            }{
    
    
                name: "Like",
            }
            describe(strt)
        }

        // type = string, value= Hello World
        // type = int, value= 55
        // type = struct { name string }, value= {Like}

5. Type assertion

        func assert(i interface{
    
    }) {
    
    
            s := i.(int)
            fmt.Println(s)
            //v, s := i.(int)
            //fmt.Println(v, s) // 56, true 如果是两个值 则是值和true or false
        }

        func main() {
    
    
            var i interface{
    
    } = 56
            assert(i) // 56
            var s interface{
    
    } = "Like"
            assert(s) // panic: interface conversion: interface {} is string, not int
        }

6. Type switch

        func findType(i interface{
    
    }) {
    
    
            switch i.(type) {
    
    
            case string:
                fmt.Printf("I am string and my value is %s\n", i.(string))
            case int:
                fmt.Printf("I am an int and my value is %d\n", i.(int))
            default:
                fmt.Printf("Unknown type\n")
            }
        }

        func main() {
    
    
            findType("Like")
            findType(666)
            findType(66.99)
        }

        // I am string and my value is Like
        // I am an int and my value is 666
        // Unknown type

7. Implementing interfaces using pointer receivers VS value receivers

        package main

        import "fmt"

        type Describer interface {
    
    
            Describe()
        }

        type Person struct {
    
    
            name string
            age  int
        }

        type Address struct {
    
    
            state   string
            country string
        }

        func (p Person) Describe() {
    
    
            fmt.Printf("%s is %d years old\n", p.name, p.age)
        }

        func (a *Address) Describe() {
    
    
            fmt.Printf("State %s Counrty %s", a.state, a.country)
        }

        func main() {
    
    
            var d1 Describer
            p1 := Person{
    
    "Like", 11}
            d1 = p1
            d1.Describe() // Like is 11 years old

            p2 := Person{
    
    "Jack", 22}
            d1 = &p2      //{Jack 22}
            d1.Describe() // Jack is 22 years old

            var d2 Describer
            a := Address{
    
    "LiangXiaoXiao", "China"}
            d2 = &a
            d2.Describe() // State LiangXiaoXiao Counrty China
        }


        // Like is 11 years old
        // Jack is 22 years old
        // State LiangXiaoXiao Counrty China`

8. Implementing multiple interfaces

        type SalaryCalculators interface {
    
    
            DisplaySalary()
        }

        type LeaveCalculator interface {
    
    
            CalculateLeavesLeft() int
        }

        type Employee struct {
    
    
            firstName   string
            lastName    string
            basicPay    int
            pf          int
            totalLeaves int
            leavesTaken int
        }

        func (e Employee) DisplaySalary() {
    
    
            fmt.Printf("%s %s has salary $%d", e.firstName, e.lastName, (e.basicPay + e.pf))
        }

        func (e Employee) CalculateLeavesLeft() int {
    
    
            return e.totalLeaves - e.leavesTaken
        }

        func main() {
    
    
            e := Employee{
    
    
                firstName:   "Naveen",
                lastName:    "Ramanathan",
                basicPay:    5000,
                pf:          200,
                totalLeaves: 30,
                leavesTaken: 5,
            }
            var s SalaryCalculators = e
            s.DisplaySalary()
            var l LeaveCalculator = e
            fmt.Println("\nLeaves left =", l.CalculateLeavesLeft())
        }

        // Naveen Ramanathan has salary $5200
        // Leaves left = 25

9. Embedding interfaces

        type SalaryCalculators interface {
    
    
            DisplaySalary()
        }

        type LeaveCalculator interface {
    
    
            CalculateLeavesLeft() int
        }

        type EmployeeOperations interface {
    
    
            SalaryCalculators
            LeaveCalculator
        }

        type Employee struct {
    
    
            firstName   string
            lastName    string
            basicPay    int
            pf          int
            totalLeaves int
            leavesTaken int
        }

        func (e Employee) DisplaySalary() {
    
    
            fmt.Printf("%s %s has salary $%d", e.firstName, e.lastName, (e.basicPay + e.pf))
        }

        func (e Employee) CalculateLeavesLeft() int {
    
    
            return e.totalLeaves - e.leavesTaken
        }

        func main() {
    
    
            e := Employee{
    
    
                firstName:   "Naveen",
                lastName:    "Ramanathan",
                basicPay:    5000,
                pf:          200,
                totalLeaves: 30,
                leavesTaken: 5,
            }
            var s EmployeeOperations = e
            s.DisplaySalary()
            fmt.Println("\nLeaves left =", s.CalculateLeavesLeft())
        }

        // Naveen Ramanathan has salary $5200
        // Leaves left = 25

10. Zero value of Interface

        package main

        import "fmt"

        type Describer interface {
    
      
            Describe()
        }

        func main() {
    
      
            var d1 Describer
            if d1 == nil {
    
    
                fmt.Printf("d1 is nil and has type %T value %v\n", d1, d1)
            }
        }

        // d1 is nil and has type <nil> value <nil> 

二、Goroutines

1. How to start a Goroutine?

        package main

        import (
            "fmt"
            "time"
        )

        func hello() {
    
    
            fmt.Println("Hello world goroutine")
        }

        func main() {
    
    
            go hello()                  // 没有等待完成就下一步了
            time.Sleep(1 * time.Second) // 优化添加io操作 则看见了运行hello的输入
            fmt.Println("main function")
        }

2. Starting multiple Goroutines

        package main

        import (  
            "fmt"
            "time"
        )

        func numbers() {
    
      
            for i := 1; i <= 5; i++ {
    
    
                time.Sleep(250 * time.Millisecond)
                fmt.Printf("%d ", i)
            }
        }
        func alphabets() {
    
      
            for i := 'a'; i <= 'e'; i++ {
    
    
                time.Sleep(400 * time.Millisecond)
                fmt.Printf("%c ", i)
            }
        }
        func main() {
    
      
            go numbers()
            go alphabets()
            time.Sleep(3000 * time.Millisecond)
            fmt.Println("main terminated")
        }

        // 1a23b4c5deMain Terminated

三、Channels

1. Declaring channels

        package main

        import "fmt"

        func main() {
    
    
            var a chan int
            if a == nil {
    
    
                fmt.Println("Channel a is nil, going to define it")
                a = make(chan int)
                fmt.Printf("Type of a is %T", a)
            }
        }


        // Channel a is nil, going to define it
        // Type of a is chan int

2. Channel example program

        package main

        import (
            "fmt"
            "time"
        )

        func hello(done chan bool) {
    
    
            fmt.Println("Hello go routine is going to sleep")
            time.Sleep(4 * time.Second)
            fmt.Println("hello go routine awake and going to write to done")
            done <- true // 将 true发送给done通道 表示hello结束运行
        }

        func main() {
    
    
            done := make(chan bool) // 创建done通道 bool类型
            fmt.Println("Main going to call hello go goroutine")
            go hello(done) // 启动goroutine线程并发 不会阻塞主线程 运行hello
            <-done         //  done 通道接收数据 阻塞操作 直到接收到数据为止 hello发送了true解除阻塞
            time.Sleep(1 * time.Second)
            fmt.Println("Main received data")
        }

        // Main going to call hello go goroutine
        // Hello go routine is going to sleep
        // hello go routine awake and going to write to done
        // Main received data

3. Another example for channels

        package main

        import (  
            "fmt"
        )

        func calcSquares(number int, squareop chan int) {
    
      
            sum := 0
            for number != 0 {
    
    
                digit := number % 10
                sum += digit * digit
                number /= 10
            }
            squareop <- sum
        }

        func calcCubes(number int, cubeop chan int) {
    
      
            sum := 0 
            for number != 0 {
    
    
                digit := number % 10
                sum += digit * digit * digit
                number /= 10
            }
            cubeop <- sum
        } 

        func main() {
    
      
            number := 589
            sqrch := make(chan int)
            cubech := make(chan int)
            go calcSquares(number, sqrch)
            go calcCubes(number, cubech)
            squares, cubes := <-sqrch, <-cubech
            fmt.Println("Final output", squares + cubes)
        }

        // Final output 1536  

4. Deadlock

        package main

        func main() {
    
      
            ch := make(chan int)
            ch <- 5
        }


        // fatal error: all goroutines are asleep - deadlock!

        // goroutine 1 [chan send]:
        // main.main()
        //        D:/one/channel.go:34 +0x31

5. Unidirectional channels

        func sendData(sendch chan<- int) {
    
    
            sendch <- 10
        }

        func main() {
    
    
            chnl := make(chan int)
            go sendData(chnl)
            fmt.Println(<-chnl) // 接收数据 并打印
        }

        // 10

6. Closing channels and for range loops on channels

        func producer(chnl chan int) {
    
    
            for i := 0; i < 10; i++ {
    
    
                chnl <- i
            }
            close(chnl)
        }

        func main() {
    
    
            ch := make(chan int)
            go producer(ch)
            for {
    
    
                v, ok := <-ch
                fmt.Println(v, ok)
                if ok == false {
    
    
                    break
                }
                fmt.Println("Received", v, ok)
            }
        }


         // Received  0 true  
         // Received  1 true  
         // Received  2 true  
         // Received  3 true  
         // Received  4 true  
         // Received  5 true  
         // Received  6 true  
         // Received  7 true  
         // Received  8 true  
         // Received  9 true 

猜你喜欢

转载自blog.csdn.net/MeiJin_/article/details/132324850