Go套路 Scan 轮询变中断

V1.0

package main

import (
	"fmt"
	"time"
)

func loopcheck(ch chan bool) {
	var i int = 0
	for {
		time.Sleep(time.Second)
		i++
		if i == int(2) {
			ch <- true
		}
	}
}
func main() {
	ch := make(chan bool)
	go loopcheck(ch)
	ticker_period := 1000 * time.Millisecond
	t := time.NewTicker(ticker_period)
	for {
		select {
		case b := <-ch:
			fmt.Println("中断收到啦!", b)
		case <-t.C:
			fmt.Println("main")
		}
	}
}

可以但是有个任务没有停止!

V2

package main

import (
	"fmt"
	"time"
)

func loopcheck(ch chan bool) {
	var i int = 0
	if ch == nil {
		fmt.Println("loopcheck die")
		time.Sleep(time.Second)
		return
	}
	for {
		time.Sleep(time.Second)
		i++
		if i == int(2) {
			ch <- true
		}
	}
}
func main() {
	ch := make(chan bool)
	go loopcheck(ch)
	ticker_period := 1000 * time.Millisecond
	t := time.NewTicker(ticker_period)
	for {
		select {
		case b := <-ch:
			fmt.Println("中断收到啦!", b)
			close(ch)
		case <-t.C:
			fmt.Println("main")
		}
	}
}

他的测试是

[Running] go run "c:\Users\Koson.Gong\Desktop\sgo\my\myselfkill.go"

main

main

中断收到啦! true

中断收到啦! false

panic: close of closed channel

goroutine 1 [running]:

main.main()

    c:/Users/Koson.Gong/Desktop/sgo/my/myselfkill.go:32 +0x17a

exit status 2

所以我没有必要去关闭了 因为他已经关闭了 !

怎么会关闭的呢? 奇怪啊

V3用这个把

package main

import (
	"fmt"
	"time"
)

func loopcheck(ch chan bool) {
	var i int = 0
	/*
		这个办法C风格太强 不好 使用Go风格的
	*/
	/*
		for {
			time.Sleep(800 * time.Millisecond)
			i++
			if i == int(2) {
				//close(ch)
				ch <- true
				return
			}
		}
	*/

	ticker_period := 800 * time.Millisecond
	t := time.NewTicker(ticker_period)
	for {
		select {
		case <-t.C:
			i++
			fmt.Println(i)
			if i == int(2) {
				//close(ch)
				ch <- true
				return //自动消亡这个协程
			}
		}
	}

}
func main() {
	ch := make(chan bool)
	go loopcheck(ch)
	ticker_period := 1000 * time.Millisecond
	t := time.NewTicker(ticker_period)
	for {
		select {
		case b := <-ch:
			fmt.Println("中断收到啦!", b)
		case <-t.C:
			fmt.Println("main")
		}
	}
}

遗留问题 即时 谁关闭的?

package main

import (
	"fmt"
	"time"
)

func loopcheck(ch chan bool) {
	var cnt int = 0
	ticker_period := 800 * time.Millisecond
	t := time.NewTicker(ticker_period)
	for {
		select {

		case <-t.C:
			fmt.Println(cnt)
			cnt++
			if cnt == 3 {
				//close(ch)
				ch <- true
			}
		}
	}
}
func main() {
	ch := make(chan bool, 2)
	go loopcheck(ch)
	ticker_period := 1000 * time.Millisecond
	t := time.NewTicker(ticker_period)
	for {
		select {
		//case b := <-ch:
		//	fmt.Println("中断收到啦!", b)
		case <-ch:
			if x, ok := <-ch; ok {
				fmt.Println("中断收到啦!", x)
			}
		case <-t.C:
			fmt.Println("main")//这个代码测试有问题 前面的case会把后面的case抢占
		}
	}
}

带着这个问题 学习TingGo的SCAN

先看MUKA的

package api
import 	"github.com/muka/go-bluetooth/bluez/profile/adapter"

func Discover(a *adapter.Adapter1, filter *adapter.DiscoveryFilter,)//参数
             (chan *adapter.DeviceDiscovered, func(), error) {//返回值 看后图

	a.SetPairable(false)//操作参数1 adapter
	a.SetDiscoverable(false)//操作参数1 adapter 所以不能主从一体了吗?
    a.SetPowered(true)//操作参数1 adapter

	filterMap := make(map[string]interface{})
	if filter != nil {//操作参数2 万能过滤器 自己去转化ToMap
		filterMap = filter.ToMap()
	}
	a.SetDiscoveryFilter(filterMap)//操作参数1
	a.StartDiscovery()//操作参数1

	ch, discoveryCancel, err := a.OnDeviceDiscovered()
	cancel := func() {
		a.StopDiscovery()
		discoveryCancel()
	}
	return ch, cancel, nil
	/*
	返回结果1--是ch--------它来自a.OnDeviceDiscovered 所以OnDeviceDiscovered是关键
	返回结果2--是一个函数---你调用它就是调用了i-a.StopDiscovery II-discoveryCancel
	
	*/
}

自己写小程序 效果一样 重复关闭

package main

import (
	"fmt"
	"time"
)

func loopcheck() (chan bool, func()) {

	ch := make(chan bool)
	go func() {
		var i int = 0
		for {
			time.Sleep(time.Second)
			i++
			if i == int(3) {
				ch <- true
			}
		}
	}()
	cancel := func() {
		close(ch)
	}
	return ch, cancel
}
func main() {
	c, fun := loopcheck()
	ticker_period := 1000 * time.Millisecond
	t := time.NewTicker(ticker_period)
	for {
		select {
		case b := <-c:
			fmt.Println("中断收到啦!", b)
			fun()
		case <-t.C:
			fmt.Println("main")
		}
	}
}

scan是怎么做的

这个 怎么写一个毒杀函数

package main

import (
	"fmt"
	"time"
)

type Adapter struct {
	cancelChan chan struct{}
	num        int
}

func (a *Adapter) Scan(callback func(*Adapter)) bool {
	if a.cancelChan != nil {
		fmt.Println("ERR Scan")
		return false
	}
	/*
		程序进来的时候 通道 a.cancelChan 必须是关闭的
		因为我马上回给他重写分配内存的

		通道是谁关闭的?是用户自己再外面回调关闭的
	*/
	cancelChan := make(chan struct{})
	a.cancelChan = cancelChan
	for {
		a.num++
		time.Sleep(time.Second)
		fmt.Println(a.num)
		if a.num%int(3) == 0 {
			fmt.Println("条件何时 扫到东西 执行一次")
			callback(a)
		}
	}
}

func (a *Adapter) StopScan() bool {
	if a.cancelChan == nil {
		fmt.Println("ERR StopScan")
		return false
	}
	close(a.cancelChan)
	a.cancelChan = nil
	fmt.Println("StopScan")
	return true
}

func main() {
	var A Adapter = Adapter{num: 0}
	A.Scan(
		func(B *Adapter) {
			fmt.Println("B.num", B.num)
			if B.num == int(6) {
				B.StopScan()
			}
		})

	for {
	}
}

/*

Koson.Gong@MC2077 MINGW64 ~/Desktop/sgo/my (master)
$ go build myscan.go

Koson.Gong@MC2077 MINGW64 ~/Desktop/sgo/my (master)
$ ./myscan.exe
1
2
3
条件何时 扫到东西 执行一次
B.num 3
4
5
6
条件何时 扫到东西 执行一次
B.num 6
StopScan
7
8
9
条件何时 扫到东西 执行一次
B.num 9
10

*/

修改 也不行

package main

import (
	"fmt"
	"time"
)

type Adapter struct {
	cancelChan chan struct{}
	num        int
}

func (a *Adapter) Scan(callback func(*Adapter)) bool {
	if a.cancelChan != nil {
		fmt.Println("ERR Scan")
		return false
	}
	/*
		程序进来的时候 通道 a.cancelChan 必须是关闭的
		因为我马上回给他重写分配内存的

		通道是谁关闭的?是用户自己再外面回调关闭的
	*/
	cancelChan := make(chan struct{})
	a.cancelChan = cancelChan
	go func() {
		for {
			a.num++
			time.Sleep(time.Second)
			fmt.Println(a.num)
			if a.num%int(3) == 0 {
				fmt.Println("条件何时 扫到东西 执行一次")
				callback(a)
			}
		}
	}()
	for {
		select {
		case <-cancelChan:
			fmt.Println("--- OUT ---")
			return true
		}
	}
}

func (a *Adapter) StopScan() bool {
	if a.cancelChan == nil {
		fmt.Println("ERR StopScan")
		return false
	}
	close(a.cancelChan)
	a.cancelChan = nil
	fmt.Println("StopScan")
	return true
}

func main() {
	var A Adapter = Adapter{num: 0}
	A.Scan(
		func(B *Adapter) {
			fmt.Println("B.num", B.num)
			if B.num == int(6) {
				B.StopScan()
			}
		})

	for {
	}
}

/*

Koson.Gong@MC2077 MINGW64 ~/Desktop/sgo/my (master)
$ go build myscan.go

Koson.Gong@MC2077 MINGW64 ~/Desktop/sgo/my (master)
$ ./myscan.exe
1
2
3
条件何时 扫到东西 执行一次
B.num 3
4
5
6
条件何时 扫到东西 执行一次
B.num 6
StopScan
7
8
9
条件何时 扫到东西 执行一次
B.num 9
10

*/

不能再里面继续go了!

下面终于成功了!!!

package main

import (
	"fmt"
	"time"
)

type Adapter struct {
	cancelChan chan struct{}
	num        int
}

func (a *Adapter) Scan(callback func(*Adapter)) bool {
	if a.cancelChan != nil {
		fmt.Println("ERR Scan")
		return false
	}
	/*
		程序进来的时候 通道 a.cancelChan 必须是关闭的
		因为我马上回给他重写分配内存的

		通道是谁关闭的?是用户自己再外面回调关闭的
	*/
	cancelChan := make(chan struct{})
	a.cancelChan = cancelChan

	ticker_period := 1000 * time.Millisecond
	t := time.NewTicker(ticker_period)
	for {
		select {
		case <-t.C:
			a.num++
			fmt.Println(a.num)
			callback(a)
		case <-cancelChan:
			fmt.Println("--OUT---")
			return true
		}

	}
}

func (a *Adapter) StopScan() bool {
	if a.cancelChan == nil {
		fmt.Println("ERR StopScan")
		return false
	}
	close(a.cancelChan)
	a.cancelChan = nil
	fmt.Println("StopScan")
	return true
}

func main() {
	var A Adapter = Adapter{num: 0}
	A.Scan(
		func(B *Adapter) {//这里的B其实也是A 因为调用再Scan里面赋值了A
			fmt.Println("B.num", B.num)
			if B.num == int(6) {
				B.StopScan()
			}
		})

	for {
	}
}

可以利用它完成轮询变中断!

比如过一段时间 断开连接

package main

import (
	"fmt"
	"time"
)

type BleStatus struct {
	cancelChan  chan struct{}
	isconnected bool
}

func (a *BleStatus) Check(callback func(*BleStatus)) {
	if a.cancelChan != nil {
		fmt.Println("ERR Scan")
		return
	}

	cancelChan := make(chan struct{})
	a.cancelChan = cancelChan

	ticker_period := 1000 * time.Millisecond
	t := time.NewTicker(ticker_period)
	var num int = 0
	for {
		select {
		case <-t.C:
			num++
			fmt.Println(num)
			if num == 3 {
				a.isconnected = false
			}
			callback(a)
		case <-cancelChan:
			fmt.Println("--OUT---")
			return
		}

	}
}

func (a *BleStatus) StopCheck() bool {
	if a.cancelChan == nil {
		fmt.Println("ERR StopCheck")
		return false
	}
	close(a.cancelChan)
	a.cancelChan = nil
	fmt.Println("StopCheck")
	return true
}

func main() {
	var A BleStatus = BleStatus{isconnected: true}
	A.Check(
		func(B *BleStatus) { //这里的B其实也是A 因为调用再Scan里面赋值了A
			fmt.Println("B.num", B.isconnected)
			if B.isconnected == false {
				B.StopCheck()
			}
		})
	fmt.Println("HELLO WORLD")
	for {
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值