Go基础(三) | 青训营笔记

70 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天

GO基础(三)

接口

package Test
​
import "testing"// 定义一个接口
type Programmer interface {
    WriteHelloWorld() string
}
​
type GoProgrammer struct {
}
​
func (g *GoProgrammer) WriteHelloWorld() string {
    return "fmt.println("Hello World")"
}
​
func TestClient(t *testing.T) {
    var p Programmer
    p = new(GoProgrammer)
    t.Log(p.WriteHelloWorld())
}

接口差异

1.接口为非侵入性,实现不依赖于接口定义

2.所以接口的定义可以包含在接口使用者包内

空接口和断言

1.空接口可以表示任何类型

2.通过断言来将空接口转换为制定类型

v,ok :=p.(int)  //ok=true 时转换成功

Go接口最佳选择

1.倾向于使用小的接口定义,很多接口只包含一个方法

2.较大的接口定义,可以由多个小接口定义组合而成

3.只依赖于必要功能的小接口

错误机制

差异

  1. 没有异常机制
  2. error 类型实现了error接口
  3. 可以通过errors.New来快速创建错误实例
  4. 尽早失败,防止嵌套

可复用模块

package包

  1. 基本复用模块单元,以首字母大写来表明可以被包外代码访问
  2. 代码的package可以和所在的目录不一致
  3. 同一个目录里的Go代码的package要一致

init方法

  1. 在main被执行前,所有依赖的package的init方法都会被执行
  2. 不同包的init函数按照包导入的依赖关系决定执行顺序
  3. 每个包可以有多个init函数
  4. 包的每个源文件也可以有多个init函数

并发机制

协程机制

package Test
import (
    "fmt"
    "testing"
)
​
func TestGroutine(t *testing.T) {
    for i := 0; i < 10; i++ {
        go func(i int) { //在方法名前加go为协程
            fmt.Println(i)
        }(i)
    }
​
}

共享内存

func TestShare(t *testing.T) {
    counter := 0//创建五千个线程
    for i := 0; i < 5000; i++ {
        go func() {
            counter++
        }()
    }
    time.Sleep(1 * time.Second)
    t.Log(counter)
}
​
//线程不安全,导致coubter!=5000

package Test
​
import (
    "sync"
    "testing"
    "time"
)
​
func TestShare(t *testing.T) {
    var mut sync.Mutex
    counter := 0
    //创建五千个线程
    for i := 0; i < 5000; i++ {
        go func() {
            defer func() {
                mut.Unlock()
            }()
            mut.Lock()
            counter++
        }()
    }
    time.Sleep(1 * time.Second)
    t.Log(counter)
}

等待

上面代码使用time.Sleep方法等待所有协程执行完毕,实际上应该使用wait方法等待线程执行完毕

package Test
​
import (
    "sync"
    "testing"
)
​
func TestShare(t *testing.T) {
    var mut sync.Mutex
    var wg sync.WaitGroup
    counter := 0
    //创建五千个线程
    for i := 0; i < 5000; i++ {
        wg.Add(1)
        go func() {
            defer func() {
                mut.Unlock()
            }()
            mut.Lock()
            counter++
            wg.Done()
        }()
    }
    wg.Wait()
    t.Log(counter)
}