golang golang上下文和渠道的例子

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang golang上下文和渠道的例子相关的知识,希望对你有一定的参考价值。

package tasks

import (
	"context"
	"log"
	"sync"
	"time"
)

type ctxExamplesKey string

func ExampleSimpleContext() {
	wg := &sync.WaitGroup{}

	start := time.Now()
	estop := make(chan time.Time, 1)
	ectx := context.Background()

	ctx, cancel := context.WithCancel(ectx) // with cancel needed to be able to do
	stop1 := make(chan time.Time, 1)
	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			select {
			case <-ctx.Done():
				log.Println("done ctx")
				stop1 <- time.Now()
				return
			case <-time.After(1 * time.Second):
				log.Println("iteration for ctx")
			}
		}
	}()

	wg.Add(1)
	go func() {
		defer func() {
			estop <- time.Now()
			wg.Done()
		}()
		for {
			select {
			case <-ectx.Done():
				log.Println("done ectx, should not occur")
				return
			case <-time.After(1 * time.Second):
				log.Println("iteration for ectx because nil channel blocks forever")
				select {
				case <-ctx.Done():
					log.Println("done ectx through escaping with ctx.Done()")
					return
				default:
				}
			}
		}
	}()

	ctx2 := context.WithValue(ctx, ctxExamplesKey("ctx2val"), 0)
	stop2 := make(chan time.Time, 1)
	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			select {
			case <-ctx2.Done():
				log.Println("done ctx2")
				stop2 <- time.Now()
				return
			default:
				time.Sleep(2 * time.Second)
				log.Println("iteration for ctx2")
				ctx2 = context.WithValue(ctx2, ctxExamplesKey("ctx2val"), ctx2.Value(ctxExamplesKey("ctx2val")).(int)+1)
			}
		}
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		<-time.After(9 * time.Second)
		cancel()
		log.Println("iteration for ctx")
	}()

	wg.Wait()

	log.Printf("ctx2val (ctx): %v", ctx.Value(ctxExamplesKey("ctx2val")))
	log.Printf("ctx2val (ctx2): %d", ctx2.Value(ctxExamplesKey("ctx2val")))
	log.Println("took", time.Now().Sub(start))
	log.Printf("ectx took: %v", (<-estop).Sub(start))
	log.Printf("ctx took: %v", (<-stop1).Sub(start))
	log.Printf("ctx2 took: %v", (<-stop2).Sub(start))
}
package channel

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

func ExampleUnbufferedSend() {
	c1 := make(chan string)

	wg := &sync.WaitGroup{}
	wg.Add(1)
	go func() {
		defer wg.Done()
		select {
		case c1 <- "got message":
			return
		case <-time.After(20 * time.Millisecond):
			return
		}
	}()

	wg.Wait() // explicitly defer until goroutine is done
	select {
	case msg := <-c1:
		fmt.Println(msg)
	default:
		fmt.Println("no message")
	}

	// Output: no message
}

func ExampleBufferedSend() {
	c1 := make(chan string, 1)

	wg := &sync.WaitGroup{}
	wg.Add(1)
	go func() {
		defer wg.Done()
		select {
		case c1 <- "got message":
			return
		case <-time.After(20 * time.Millisecond):
			return
		}
	}()

	wg.Wait() // explicitly defer until goroutine is done
	select {
	case msg := <-c1:
		fmt.Println(msg)
	default:
		fmt.Println("no message")
	}

	// Output: got message
}

func ExampleNilChannelSend() {
	var c1 chan string

	wg := &sync.WaitGroup{}
	wg.Add(1)

	result := make(chan string, 1)
	go func() {
		defer wg.Done()
		select {
		case c1 <- "got message":
			return
		case <-time.After(20 * time.Millisecond):
			result <- "nil channel send blocks"
			return
		}
	}()

	wg.Wait()
	select {
	case msg := <-c1:
		fmt.Println(msg)
	case msg := <-result:
		fmt.Println(msg)
	}

	// Output: nil channel send blocks
}

func ExampleClosedChannelSend() {
	c1 := make(chan string, 1)
	close(c1)

	// using a channel so we know when its done
	result := make(chan string)
	go func() {
		defer func() {
			if r := recover(); r != nil { // handling the panic of the send on closed channel that will happen below
				result <- r.(error).Error()
				return
			}
			result <- "timed out"
		}()
		select {
		case c1 <- "got message": // closed channels panic when you send on them
			return
		case <-time.After(20 * time.Millisecond):
			return
		}
	}()

	fmt.Println(<-result)

	// Output: send on closed channel
}

func ExampleCloseNilChannel() {
	defer func() {
		if r := recover(); r != nil { // handling the panic of the close of nil channel
			fmt.Println(r)
			return
		}
		fmt.Println("timed out")
	}()

	var c1 chan string
	close(c1) // close of nil channel panics

	// Output: close of nil channel
}

func ExampleWaitArbitraryNumberOfChannels() {

}

设计模式这样玩泰简单(Golang版)-状态模式

场景

老板:我们现在要开发一个文档系统,支持多种模式,在预览模式下只支持预览操作.编辑模式下,支持增删改查操作,你有什么好的方案
你:好的老板,那就使用状态模式

方案


状态模式:我们通过状态对象封装了对上下文的动作.用不同的状态对象维护着对上下文对象操作的不同实现,达到可以横向扩展的效果.
在这个例子中,我们把文档系统当成如图所示的上下文,里面维护几个不同的状态,预览状态、编辑状态,再把我们的增删改查的动作封装到这些状态里面,通过上下文对象去使用它们.以后我们如果要扩张其他的模式,增加一个状态即可.
注意,这里要区分跟策略模式的区别,这些状态是维护在上下文内部的,客户端直接操作上下文对象,不会操作到状态对象,状态对象作为上下文的一部分组成而存在.下面,我们看看对这个例子的实现

实现

package main

import "fmt"

type Stage interface {//状态接口
   Add()
   Delete()
   Update()
   Get()
}

type context struct {
   currentState Stage//当前状态
   currentStateIndex int//当前状态索引
   innerStates []Stage//状态列表
}

func (ctx *context) ChangeState() {//切换状态
   fmt.Println("切换状态")
   ctx.currentStateIndex=ctx.currentStateIndex+1
   ctx.currentStateIndex%=len(ctx.innerStates)
   ctx.currentState=ctx.innerStates[ctx.currentStateIndex]
}

func (ctx *context) Work(){//上下文工作
   ctx.currentState.Add()
   ctx.currentState.Delete()
   ctx.currentState.Update()
   ctx.currentState.Get()
}

func Init() *context{//初始化一个上下文
   ctx:=&context{
   	innerStates:[]Stage{&PreviewState{},&EditState{}},
   }
   ctx.currentStateIndex=0
   ctx.currentState=ctx.innerStates[ctx.currentStateIndex]
   return ctx
}

//下面是两个不同状态的实现
type PreviewState struct {
   
}

func (state *PreviewState) Add()  {
   fmt.Println("[预览模式]不支持增加操作")
}

func (state *PreviewState) Delete()  {
   fmt.Println("[预览模式]不支持删除操作")
}

func (state *PreviewState) Update()  {
   fmt.Println("[预览模式]不支持更新操作")
}

func (state *PreviewState) Get()  {
   fmt.Println("[预览模式]查阅文档")
}

type EditState struct {

}

func (state *EditState) Add()  {
   fmt.Println("[编辑模式]增加文档")
}

func (state *EditState) Delete()  {
   fmt.Println("[编辑模式]删除文档")
}

func (state *EditState) Update()  {
   fmt.Println("[编辑模式]更新文档")
}

func (state *EditState) Get()  {
   fmt.Println("[编辑模式]查阅文档")
}


func main(){
   ctx:=Init()
   ctx.Work()
   ctx.ChangeState()
   ctx.Work()
}

以上是关于golang golang上下文和渠道的例子的主要内容,如果未能解决你的问题,请参考以下文章

golang golang上下文和渠道的例子

Golang 编译时发送到零通道 [关闭]

渠道是做啥用的?

设计模式这样玩泰简单(Golang版)-状态模式

设计模式这样玩泰简单(Golang版)-状态模式

设计模式这样玩泰简单(Golang版)-状态模式