職案人

求職・歴史・仏教などについて掲載するつもりだが、自分の思いつきが多いブログだよ。適当に付き合って下さい。

ゴルーチン--バッファー付きチャンネル

2023年04月30日 | GO言語
バッファー付きチャンネル


【開発環境】
OS:Win11(64ビット)
go version go1.19.4 windows/amd64
VSCode1.72.2、及びコマンドプロンプト

【バッファー付きチャンネルの利点】
複数のデーターを送受信するときに、バッファー付きチャンネルを利用すると良い

【バッファー付きチャンネルの作成】
make()を使って作る。

・例文
// make関数を使用してchannelとしての機能を持たせる
// bool型でバッファサイズは「3」を指定する。、
done := make(chan bool,3)
作成されるチャンネルは非同期です

・サンプルコード
//buffer.go
package main

import (
"fmt"
"time"
)

func main(){
//チャンネルを作る
// bool型でバッファサイズは「3」を指定する
done := make(chan bool, 3)

//ゴルーチンで"+"を出力する
go func () {
for i := 0; i < 10; i++ {
time.Sleep(10 * time.Millisecond)
fmt.Printf("+")
}
done <- true //終わったらtrueを送る

}()
//ゴルーチンで"-"を出力する
go func () {
for i := 0; i < 9; i++ {
time.Sleep(9 * time.Millisecond)
fmt.Printf("-")
}
done <- true //終わったらtrueを送る

}()
//ゴルーチンで""を出力する
go func () {
for i := 0; i < 10; i++ {
time.Sleep(10 * time.Millisecond)
fmt.Printf("")
}
done <- true //終わったらtrueを送る

}()
//ゴルーチンで"/"を出力する
for i := 0; i < 10; i++ {
fmt.Printf("/")
time.Sleep(5 * time.Millisecond)
}
for i := 0; i < 3; i++ {
<-done //trueが送られるのを待って受け取る
}

}

・実行
PS D:\GO言語\サンプルプログラム\Go-8> go run buffer.go
//+-\+/\-\-/++-/\+-/\\-/+\-/+\-/++-\/\+
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

ゴルーチンのselect文

2023年04月23日 | GO言語
select文


【開発環境】
OS:Win11(64ビット)
go version go1.19.4 windows/amd64
VSCode1.72.2、及びコマンドプロンプト

◆select文
select文はチヤンネルの送受に応じて処理を切り替える事ができる。

例1
select {
case v1 = <-ch1:
//ch1から受け取ったv1に保存された値を使う
case v2 = <-ch2:
//ch2に値v2を送信する
default:
//通信がない時

・サンプルコード
// selchan.go
package main

import (
"fmt"
"time"
)

func main() {
//チャンネルを作る
ch1 := make(chan rune)
ch2 := make(chan int)
done := make(chan bool)

//ゴルーチン
go func () {
s := "ABCDEFG"
for _, c := range s{
time.Sleep(10 * time.Millisecond)
fmt.Printf("ch1から送電:%c\n",c)
ch1 <- c
}
done <- true //終わったらtrueを送る

}()

//ゴルーチン数値を送る
go func () {
for i := 0;i < 0;i++ {
time.Sleep(8 * time.Millisecond)
fmt.Printf("ch2から送信:%d\n",i)
ch2 <- i+1
}
done <- true //終わったらtureを送る
}()

defer fmt.Println("終了")
count := 0

//メインルーチンで受け取ったデータを出力
for {
select {
case r := <-ch1:
fmt.Printf("ch1から受信:%d\n",r)
case n := <-ch2:
fmt.Printf("ch2から受信:%d\n",n)
case <-done: // trueが2個送られたら終了
count++
if count > 1{
return
}

   }
   }
}


・実行
PS D:\GO言語\サンプルプログラム\Go-8> go run selchan.go
ch1から送電:A
ch1から受信:65
ch1から送電:B
ch1から受信:66
ch1から送電:D
ch1から受信:68
ch1から送電:E
ch1から受信:69
ch1から送電:F
ch1から受信:70
ch1から送電:G
ch1から受信:71
終了
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

ゴルーチン間の通信(チャンネル)

2023年04月18日 | GO言語
ゴルーチン間の通信


【開発環境】
OS:Win11(64ビット)
go version go1.19.4 windows/amd64
VSCode1.72.2、及びコマンドプロンプト

【チャンネルとは】
チャンネルは同時に実行されているゴルーチン間や、メインルーチンとゴルーチンとの間で、特定の形の値を受け渡す通信機構を提供する

例えば、bool値を受け渡したいとする時、
1、チャンネルを作る
ch := make(chan bool)
これで、同期しているチャンネルが作られた。
チャンネルに情報を送る為には「<-」を用います。

2、bool型のチャンネルにtrueを送ってみる。
ch <- true

3、チャンネルから情報を受取るも、「<-」を使う
x <- ch

4、受け取った事実だけを知りたい時
<- ch

5、チャンネルから正しく受け取った受け取ったどうかの判定
x,ok := <-ch

いずれにしても、これらのコードはチャンネルから、情報を受け取るまで待ちます。

・サンプルコード
// chan.go
package main

import (
"fmt"
"time"
)

func main() {
//チャンネルを作る
done := make(chan bool)

//ゴルーチンで"+"を出力する
go func() {
for i := 0; i < 10; i++ {
time.Sleep(10 * time.Millisecond)
fmt.Printf("+")
}
done <- true //終わったらtrueを送る
}()

//メインルーチンで"/"を出力する
for i := 0; i < 10; i++ {
time.Sleep(10 * time.Millisecond)
fmt.Printf("/")
}
//trueが送られるのを待って受け取る
<- done

fmt.Printf("\n終了\n")

}
・実行
PS D:\GO言語\サンプルプログラム\Go-8> go run chan.go
+//+/++//++//++//++/
終了


コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

ゴルーチン--無名関数

2023年04月09日 | GO言語
無名関数


【開発環境】
OS:Win11(64ビット)
go version go1.19.4 windows/amd64
VSCode1.72.2、及びコマンドプロンプト

【無名関数】
ゴルーチンとして呼び出す関数として定義しなければならないと言うルールはなく、関数を呼び出す側で、名前のない関数(無名関数)を定義すれば、良い!

・無名関数の定義
 go func() {
//関数の内容
}()
・サンプルコード
// gofunc.go
package main

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

func main() {
var wg sync.WaitGroup

for _, c := range "ABC" {
ch := c
fmt.Printf("%c start\n", c)

//前回のprintjob()関数を無名関数にしている
     go func() {
wg.Add(1)
for i := 0; i < 10; i++ {
time.Sleep(10 * time.Millisecond)
fmt.Printf("%c", ch)
}
defer wg.Done() //遅延してwg.Done():デクリメントを実行する

}()
}
wg.Wait()
fmt.Printf("\n終了\n")
}

・実行
PS D:\GO言語\サンプルプログラム\Go-8> go run gofunc.go
A start
B start
C start
CABBACABCBACCABACBCABACBCABACB
終了
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

ゴルーチン---ウエイト

2023年04月05日 | GO言語
ウエイト


【開発環境】
OS:Win11(64ビット)
go version go1.19.4 windows/amd64
VSCode1.72.2、及びコマンドプロンプト

【ウェイト】
ゴルーチンの終了タイミングは正確に予想が出来ないため、ウェイトグループ(WaitGroup)を使ってゴルーチンが終了するまで待つようにする。
・サンプルコード
// gosample.go
package main

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

// sync.WaitGroupの値を保存する変数の宣言
var wg sync.WaitGroup

// 一度に文字列(厳密には文字)を1個出力すつことを10回繰り返す関数を定義する
func printjob(s string) {
defer wg.Done() //終了を待つゴルーチンの数がデクリメントされる
for i := 0; i < 10; i++ {
time.Sleep(10 * time.Millisecond)
fmt.Printf("%s", s)
}
}

// メイン
func main() {
wg.Add(3) //待つジョブを3にする

fmt.Println("A start")
go printjob("A") //ゴルーチン

fmt.Println("B start")
go printjob("B") //ゴルーチン

fmt.Println("C start")
go printjob("C") //ゴルーチン

wg.Wait() //すべてのジョブが終わるのを待つ

fmt.Printf("\n終了\n")

}
・実行
PS D:\GO言語\サンプルプログラム\Go-8> go run gosample.go
A start
B start
C start
CABACBBCAACBCABACBCBACABABCBAC←順不同
終了

【wg.Wait()を書かない場合】
PS D:\GO言語\サンプルプログラム\Go-8> go run gosample.go
A start
B start
C start
終了
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする