Go语言的学习之旅【六】

一、接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
type Car interface { //定义一个Car的接口
    what() //定义一个方法
}
type Bicycle struct {
}
type Motor struct {
}
 
func (bicycle Bicycle) what() {
    fmt.Println("I am Bicycle")
}
func (bicycle Bicycle) speed() {
    fmt.Println("I am Bicycle,speed 15km/h")
}
func (motor Motor) what() {
    fmt.Println("I am Motor")
}
 
func main() {
    var car Car
    car = new(Bicycle)
    car.what()
    car = new(Motor)
    car.what()
    var bicycle = new(Bicycle) //这个代表一个指针
    bicycle.speed()
 
}

  

二、错误异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// 定义一个 DivideError 结构
type DivideError struct {
    dividee int
    divider int
}
 
// 实现 `error` 接口
func (de *DivideError) Error() string {
    strFormat := `
    Cannot proceed, the divider is zero.
    dividee: %d
    divider: 0
`
    //fmt.Println("de:",&de)
    return fmt.Sprintf(strFormat, de.dividee)
}
// 定义 `int` 类型除法运算的函数
func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
    if varDivider == 0 {
        dData := DivideError{
            dividee: varDividee,
            divider: varDivider,
        }
        errorMsg = dData.Error()
        //fmt.Println("dData:",&dData)
        return
    } else {
        return varDividee / varDivider, ""
    }
 
}
func Sqrt(f float64) (float64, error) {
    if f < 0 {
        return 0, errors.New("math: square root of negative number")
    }
    return math.Sqrt(f), nil
}
func main() {
    var a, err = Sqrt(10)
    if err != nil {
        fmt.Println(a, err)
    }
    // 正常情况
    if result, errorMsg := Divide(100, 10); errorMsg == "" {
        fmt.Println("100/10 = ", result)
    }
    // 当除数为零的时候会返回错误信息
    if _, errorMsg := Divide(1000, 0); errorMsg != "" {
        fmt.Println("errorMsg is: ", errorMsg)
    }
}

 

三、并发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
func say(s string) {
    for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
 
}
func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
    fmt.Println(sum)
    c <- sum //把sum值发送到通道c
}
func main() {
    //go say("world") //开启新的线程
    //say("hello")    //主线程,运行可以看到world跟hello打印没有顺序,证明两个同时进行
    s := []int{7, 2, 8, -9, 4, 0}
    c := make(chan int)     //默认通道,需要一发一收
    go sum(s[:len(s)/2], c) //并发计算,里面发送信号到通道c
    go sum(s[len(s)/2:], c) //并发
    x, y := <-c, <-c        //这里接收c的通信
    fmt.Println(x, y, x+y)
    //如果构建通道时,给与缓存,可以一次性多发送,再一次性多接收
    // 因为 ch 是带缓冲的通道,我们可以同时发送两个数据
    // 而不用立刻需要去同步读取数据
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    u, v := <-ch, <-ch
    fmt.Println(u, v)
    ch2 := make(chan int, 10)
    go fibonacci(cap(ch2), ch2)
    // range 函数遍历每个从通道接收到的数据,因为 c 在发送完 10 个
    // 数据之后就关闭了通道,所以这里我们 range 函数在接收到 10 个数据
    // 之后就结束了。如果上面的 c 通道不关闭,那么 range 函数就不
    // 会结束,从而在接收第 11 个数据的时候就阻塞了。
    for i := range ch2 {
        fmt.Println(i)
    }
 
}
func fibonacci(n int, c chan int) {
    x, y := 0, 1
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x+y
    }
    close(c)
}

  

四、总结

  go语言接口方面设计确实很简洁,实现接口里的方法只要对应的结构体实现。错误处理看起来只是简单的方法调用。并发上确实简单,调用时直接加go关键词,就会新开线程同步执行。还有关于通信接收,还只是初步了解,默认情况下通道只有1,接收要同步,一发一收,否则就会阻塞形成死锁。如果给通道设置容量,可以多发多收。接触了go语言,确实在一方面有突出的点。接着会学习goweb的开发!

posted @   Auler  阅读(121)  评论(0编辑  收藏  举报
编辑推荐:
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示