10.3 Running a code block only once 只运行一次代码块

只运行一次代码块
的情况下,当多个goroutines运行相同的代码,有代码块初始化,例如,共享的资源,走标准库提供的解决方案,这将进一步描述。
package main

import (
	"fmt"
	"sync"
	"time"
)

var names = []interface{}{"Alan", "Joe", "Jack", "Ben",
	"Ellen", "Lisa", "Carl", "Steve", "Anton", "Yo"}

type Source struct {
	m    *sync.Mutex
	o    *sync.Once
	data []interface{}
}

func (s *Source) Pop() (interface{}, error) {
	s.m.Lock()
	defer s.m.Unlock()
	s.o.Do(func() {
		time.Sleep(time.Second * 3)
		s.data = names
		fmt.Println("Data has been loaded.")
	})
	if len(s.data) > 0 {
		res := s.data[0]
		s.data = s.data[1:]
		return res, nil
	}
	return nil, fmt.Errorf("No data available")
}

func main() {

	s := &Source{&sync.Mutex{}, &sync.Once{}, nil}
	wg := sync.WaitGroup{}
	wg.Add(10)
	for i := 0; i < 10; i++ {
		go func(idx int) {
			// This code block is done only once
			if val, err := s.Pop(); err == nil {
				fmt.Printf("Pop %d returned: %s\n", idx, val)
			}
			wg.Done()
		}(i)
	}
	wg.Wait()
}

/*
Data has been loaded.
Pop 1 returned: Alan
Pop 3 returned: Ben
Pop 9 returned: Joe
Pop 2 returned: Jack
Pop 4 returned: Ellen
Pop 6 returned: Carl
Pop 7 returned: Steve
Pop 8 returned: Anton
Pop 0 returned: Yo
Pop 5 returned: Lisa

 */

示例代码演示了在访问容器结构时对数据的延迟加载。由于数据应该只加载一次,所以在方法弹出中使用了同步包中的一次结构。前者只执行一个名为do的方法,该函数不需要参数就使用函数,在执行过程中每次执行一次函数只执行一次。
DO方法调用块直到第一次运行完成。这一事实与一次被用于初始化的事实相对应。

posted on 2018-03-27 00:42  cucy_to  阅读(194)  评论(0编辑  收藏  举报

导航