Last active
March 3, 2022 08:19
-
-
Save devlights/34abe278d594b12b75ccb5405fc632ff to your computer and use it in GitHub Desktop.
自分用 手慣らしの型 (go, csharp)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 自分用の手慣らしの型 | |
// 1.HttpClientでリクエストを出す(リクエストもそれぞれを非同期実行) | |
// 2.(1)の結果から <title> タグの中身を抽出 | |
// 3.(2)の結果を出力 | |
// | |
// エラー処理は面倒なので割愛している | |
// | |
// httpリクエストを非同期実行しているので | |
// 結果は毎回異なる可能性がある。 | |
// | |
// REFERENCES: | |
// - https://devlights.hatenablog.com/entry/2020/04/20/032712 | |
// - https://devblogs.microsoft.com/dotnet/an-introduction-to-system-threading-channels/ | |
// - https://deniskyashif.com/2019/12/08/csharp-channels-part-1/ | |
// - https://deniskyashif.com/2019/12/11/csharp-channels-part-2/ | |
// - https://deniskyashif.com/2020/01/07/csharp-channels-part-3/ | |
// - https://ufcpp.net/study/csharp/async/asyncstream/#await-foreach | |
// | |
using System; | |
using System.Collections.Generic; | |
using System.Threading.Tasks; | |
using System.Threading.Channels; | |
class Kata | |
{ | |
static async Task Main() | |
{ | |
var httpCh = Channel.CreateUnbounded<string>(); | |
var dataCh = Channel.CreateUnbounded<string>(); | |
var httpTask = Task.Run(async () => | |
{ | |
var urls = new string[]{ | |
"https://github.com/devlights/try-golang", | |
"https://github.com/devlights/gomy", | |
"https://github.com/devlights/goxcel", | |
"https://devlights.hatenablog.com" | |
}; | |
var outCh = httpCh.Writer; | |
var tasks = new List<Task>(); | |
foreach (var url in urls) | |
{ | |
var t = Task.Run(async () => | |
{ | |
using (var client = new HttpClient()) | |
{ | |
var resp = await client.GetAsync(url); | |
var body = await resp.Content.ReadAsStringAsync(); | |
await outCh.WriteAsync(body); | |
} | |
}); | |
tasks.Add(t); | |
} | |
await Task.WhenAll(tasks); | |
outCh.Complete(); | |
}); | |
var dataTask = Task.Run(async () => | |
{ | |
const string sTag = "<title>"; | |
const string eTag = "</title>"; | |
var inCh = httpCh.Reader; | |
var outCh = dataCh.Writer; | |
await foreach (var body in inCh.ReadAllAsync()) | |
{ | |
var sIdx = body.IndexOf(sTag); | |
var eIdx = body.IndexOf(eTag); | |
var begin = sIdx + sTag.Length; | |
var end = eIdx; | |
var data = body.Substring(begin, end - begin); | |
await outCh.WriteAsync(data); | |
} | |
outCh.Complete(); | |
}); | |
var inCh = dataCh.Reader; | |
await foreach (var data in inCh.ReadAllAsync()) | |
{ | |
Console.WriteLine(data); | |
} | |
await httpTask; | |
await dataTask; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 自分用の手慣らしの型 | |
// 1.http.Get()でリクエストを出す(リクエストもそれぞれを非同期実行) | |
// 2.(1)の結果から <title> タグの中身を抽出 | |
// 3.(2)の結果を出力 | |
// | |
// httpリクエストを非同期実行しているので | |
// 結果は毎回異なる可能性がある。 | |
// | |
package main | |
import ( | |
"bytes" | |
"errors" | |
"fmt" | |
"io" | |
"net/http" | |
"os" | |
"sync" | |
) | |
func main() { | |
var ( | |
httpCh = make(chan []byte) | |
dataCh = make(chan []byte) | |
errsCh = make(chan error, 1) | |
) | |
defer close(errsCh) | |
var ( | |
urls = []string{ | |
"https://github.com/devlights/try-golang", | |
"https://github.com/devlights/gomy", | |
"https://github.com/devlights/goxcel", | |
"https://devlights.hatenablog.com", | |
} | |
) | |
go func() { | |
defer close(httpCh) | |
var ( | |
wg sync.WaitGroup | |
) | |
wg.Add(len(urls)) | |
for _, url := range urls { | |
url := url | |
go func() { | |
defer wg.Done() | |
resp, err := http.Get(url) | |
if err != nil { | |
errsCh <- err | |
return | |
} | |
defer resp.Body.Close() | |
body, err := io.ReadAll(resp.Body) | |
if err != nil { | |
errsCh <- err | |
return | |
} | |
httpCh <- body | |
}() | |
} | |
wg.Wait() | |
}() | |
var ( | |
titleTagNotFound = errors.New("title tag does not found") | |
) | |
go func() { | |
defer close(dataCh) | |
var ( | |
sTag = []byte("<title>") | |
eTag = []byte("</title>") | |
) | |
for body := range httpCh { | |
var ( | |
start = bytes.Index(body, sTag) | |
end = bytes.Index(body, eTag) | |
) | |
if start == -1 || end == -1 { | |
errsCh <- titleTagNotFound | |
return | |
} | |
var ( | |
data = body[start+len(sTag) : end] | |
) | |
dataCh <- data | |
} | |
}() | |
LOOP: | |
for { | |
select { | |
case err := <-errsCh: | |
fmt.Fprintln(os.Stderr, err) | |
case data, open := <-dataCh: | |
if !open { | |
break LOOP | |
} | |
fmt.Printf("[title] %s\n", data) | |
} | |
} | |
fmt.Println("DONE") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment