3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

channelのsliceのselect(reflect.Selectの利用)

3
Posted at

はじめに

Goでタスクトレイに常駐させるようなツールを作りたい

systrayが使えそう

example/main.goを流し読み

go func() {
	for {
		select {
		case <-mChange.ClickedCh:
		// 略
		case <-mChecked.ClickedCh:
		// 略
		case <-mEnabled.ClickedCh:
		// 略
		case <-mUrl.ClickedCh:
		// 略
		case <-mToggle.ClickedCh:
		// 略
		case <-mQuit.ClickedCh:
		// 略
		}
	}
}()


メニューの項目が増えるとselectのcaseも増える。
できればchannelのsliceをselectで待ちたい。

解決策

Stack Over Flowにちょいどいい回答がありました。
selectそのままではなく、reflect.Selectを利用することで解決できるとのこと。
参考:How to listen to N channels dynamic select statement

サンプル

package main

import (
	"fmt"
	"reflect"
)

func main() {
	numChans := 5
	var chans [] chan struct{}

	for i := 0; i < numChans; i++ {
		tmp := make(chan struct{})
		chans = append(chans, tmp)
		go DoFunc(tmp)
	}

	cases := make([]reflect.SelectCase, len(chans))
	for i, ch := range chans {
		cases[i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ch)}
	}
	remaining := len(cases)
	for remaining > 0 {
		chosen, _, ok := reflect.Select(cases)
		if !ok {
			cases[chosen].Chan = reflect.ValueOf(nil)
			remaining -= 1
			continue
		}
		fmt.Println(chosen)
	}
}

func DoFunc(c chan<-struct{}) {
	c <- struct{}{}
	close(c)
}

タスクトレイから選択できる各メニューのchannelとそれに対応した処理を保持しておき、
メニューが選択された際にその処理を流せば実現できそうです。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?