目录

设计模式

单例模式

type Singleton struct {
}

var ins *Singleton
var once sync.Once

func New() *Singleton {
    once.Do(func() {
        fmt.Println("Create Obj")
        ins = new(Singleton)
    })
    return ins
}

func main() {

    go func() {
        ins := New()
        fmt.Println(unsafe.Pointer(ins))
    }()

    go func() {
        ins2 := New()
        fmt.Println(unsafe.Pointer(ins2))
    }()

    time.Sleep(time.Second)
}

只需要任意一个任务完成ng.B) {

// 使用有 buffer 的 Channel 来防止 Goroutine 泄漏
func runTask(i int) string {
    return strconv.Itoa(i)
}
func FirstResponse() string {
    numOfRunner := 10
    ch := make(chan string, numOfRunner) // 思考 有 buffer 与 无 buffer 的区别
    for i := 0; i < numOfRunner; i++ {
        go func(i int) {
            ret := runTask(i)
            ch <- ret // 如果这里写不进去,则协程会一直阻塞在这里,不退出
        }(i)
    }
    return <-ch
}

func main() {
    fmt.Println("Before: ", runtime.NumGoroutine())
    fmt.Println(FirstResponse())
    fmt.Println("After: ", runtime.NumGoroutine())
    fmt.Println(FirstResponse())
    fmt.Println("After: ", runtime.NumGoroutine())
    time.Sleep(time.Second)
    fmt.Println("After: ", runtime.NumGoroutine())
    time.Sleep(time.Second)
}

所有任务都完成

func runTask(i int) string {
   return "result is : " + strconv.Itoa(i)
}

func AllResponse() string {
   numOfRunner := 10
   ch := make(chan string, numOfRunner)

   for i := 0; i < numOfRunner; i++ {
      go func(i int) {
         ret := runTask(i)
         ch <- ret
      }(i)
   }
   finalRet := ""
   for j := 0; j < numOfRunner; j++ {
      finalRet += <-ch + "\n"
   }
   return finalRet
}

func main() {
   fmt.Println("Before: ", runtime.NumGoroutine())
   fmt.Println(AllResponse())
   fmt.Println("After: ", runtime.NumGoroutine())
   time.Sleep(time.Second)
   fmt.Println("Final : ", runtime.NumGoroutine())
   time.Sleep(time.Second)
}

使用Buffer Channel构造对象池


type ReusableObj struct {
}

func NewObj() *ReusableObj {
    return &ReusableObj{}
}

type ObjPool struct {
    bufChan chan *ReusableObj
}

func NewObjPool(numOfObj int) *ObjPool {
    ObjPool := &ObjPool{}
    ObjPool.bufChan = make(chan *ReusableObj, numOfObj)
    for i := 0; i < numOfObj; i++ {
        ObjPool.bufChan <- NewObj()
    }
    return ObjPool
}

func (pool *ObjPool) GetObj(timeout time.Duration) (*ReusableObj, error) {
    select {
    case ret := <-pool.bufChan:
        return ret, nil
    case <-time.After(timeout):
        return nil, errors.New("time out")
    }
}

func (pool *ObjPool) ReleaseObj(obj *ReusableObj) error {
    select {
    case pool.bufChan <- obj:
        return nil
    default:
        return errors.New("pool is full")
    }
}