From 03a0f38f921c8a4cbeacd9132bd1bb04b4a411f5 Mon Sep 17 00:00:00 2001 From: tokunagawataru Date: Sat, 30 Jun 2018 22:27:38 +0900 Subject: [PATCH 1/8] =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=94=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=82=B2=E3=83=BC=E3=83=A0=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai3-1/tokunaga/main.go | 90 ++++++++++++++++++++++++++++++++++ kadai3-1/tokunaga/main_test.go | 33 +++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 kadai3-1/tokunaga/main.go create mode 100644 kadai3-1/tokunaga/main_test.go diff --git a/kadai3-1/tokunaga/main.go b/kadai3-1/tokunaga/main.go new file mode 100644 index 0000000..24db460 --- /dev/null +++ b/kadai3-1/tokunaga/main.go @@ -0,0 +1,90 @@ +package main + +import ( + "bufio" + crand "crypto/rand" + "fmt" + "io" + "math" + "math/big" + "math/rand" + "os" + "time" +) + +var word = [...]string{ + "toukyoutokkyokyokakyoku", + "akamakigamiaomakigamikimakigami", + "sushi", + "tenpura", + "kaiken", + "nisshingeppo", + "hyappatuhyakutyu", + "kumiai", + "taiiku", + "kome", +} + +const ( + limitSec = 15 + ExitAbort = 1 +) + +func init() { + if err := serRandSeed(); err != nil { + os.Exit(ExitAbort) + } +} + +func serRandSeed() error { + seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64)) + rand.Seed(seed.Int64()) + return err +} + +func main() { + fmt.Printf("制限時間は%d秒です\n", limitSec) + + ch := input(os.Stdin) + var correctCount int + go output(ch, &correctCount) + + <-time.After(limitSec * time.Second) + finish(correctCount) +} + +func input(r io.Reader) <-chan string { + ch := make(chan string) + go read(r, ch) + return ch +} + +func read(reader io.Reader, ch chan string) { + s := bufio.NewScanner(reader) + for s.Scan() { + ch <- s.Text() + } + close(ch) +} + +func output(typeWord <-chan string, correctCount *int) { + wordCount := len(word) + for { + answerWord := word[rand.Intn(wordCount)] + fmt.Println(answerWord) + fmt.Print("> ") + typeWord := <-typeWord + if typeWord == answerWord { + fmt.Println("correct answer!") + *correctCount++ + } else { + fmt.Println("incorrect answer...") + } + fmt.Println("-----------------------------") + } +} + +func finish(correctCount int) { + fmt.Println("\n-----------FINISH!-----------") + fmt.Printf("正解数:%d\n", correctCount) +} diff --git a/kadai3-1/tokunaga/main_test.go b/kadai3-1/tokunaga/main_test.go new file mode 100644 index 0000000..c5e6d3e --- /dev/null +++ b/kadai3-1/tokunaga/main_test.go @@ -0,0 +1,33 @@ +package main + +import ( + "bytes" + "testing" +) + +func ExampleFinish() { + finish(3) + // Output: -----------FINISH!----------- + // 正解数:3 +} + +func TestInput(t *testing.T) { + inputWord := "Hello Worlds!" + inputBuf := bytes.NewBufferString(inputWord) + ch := input(inputBuf) + received := <-ch + if inputWord != received { + t.Errorf("want: receive %s from chanel, got: receive %s from chanel", inputWord, received) + } +} + +func TestRead(t *testing.T) { + input := "Hello Worlds!" + ch := make(chan string) + inputBuf := bytes.NewBufferString(input) + go read(inputBuf, ch) + received := <-ch + if input != received { + t.Errorf("want: receive %s from chanel, got: receive %s from chanel", input, received) + } +} From cf17ea26ee20fa917c7d1372addecccd2d9ba089 Mon Sep 17 00:00:00 2001 From: tokunagawataru Date: Sat, 30 Jun 2018 23:02:41 +0900 Subject: [PATCH 2/8] =?UTF-8?q?=E8=AA=B2=E9=A1=8C3-1=E3=81=AEREADME?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai3-1/tokunaga/README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 kadai3-1/tokunaga/README.md diff --git a/kadai3-1/tokunaga/README.md b/kadai3-1/tokunaga/README.md new file mode 100644 index 0000000..399505b --- /dev/null +++ b/kadai3-1/tokunaga/README.md @@ -0,0 +1,4 @@ +# 課題3-1 タイピングゲームを作ろう +- [ ] 標準出力に英単語を出す(出すものは自由) +- [ ] 標準入力から1行受け取る +- [ ] 制限時間内に何問解けたか表示する From 0a5695c160e0b9c2788909fb8450d268a56507ef Mon Sep 17 00:00:00 2001 From: tokunagawataru Date: Sun, 1 Jul 2018 02:22:13 +0900 Subject: [PATCH 3/8] =?UTF-8?q?download=E6=A9=9F=E8=83=BD=E3=81=AE?= =?UTF-8?q?=E5=AE=9F=E8=A3=85(range=E3=82=A2=E3=82=AF=E3=82=BB=E3=82=B9?= =?UTF-8?q?=E3=81=AF=E6=9C=AA=E5=AE=9F=E8=A3=85)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai3-2/tokunaga/main.go | 58 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 kadai3-2/tokunaga/main.go diff --git a/kadai3-2/tokunaga/main.go b/kadai3-2/tokunaga/main.go new file mode 100644 index 0000000..e88adc5 --- /dev/null +++ b/kadai3-2/tokunaga/main.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "fmt" + "io" + "net/http" + "os" + "path" + "time" +) + +const ( + ExitOK = iota + ExitAbort +) +const timeLayout = "2006-01-02 15:04:05" + +func main() { + flag.Parse() + if len(flag.Args()) != 1 { + fmt.Fprintln(os.Stderr, "You can only download one file at a time") + os.Exit(ExitAbort) + } + downloadPath := flag.Args()[0] + + t := time.Now() + fmt.Printf("--%s-- %s\n", t.Format(timeLayout), downloadPath) + fmt.Print("HTTP による接続要求を送信しました、応答を待っています...") + responseHead, err := http.Head(downloadPath) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(ExitAbort) + } + statusCode := responseHead.StatusCode + fmt.Printf("%d %s\n", statusCode, http.StatusText(statusCode)) + if responseHead.StatusCode != 200 { + fmt.Fprintln(os.Stderr, http.StatusText(responseHead.StatusCode)) + os.Exit(ExitAbort) + } + fmt.Printf("長さ: %d [%s]\n", responseHead.ContentLength, responseHead.Header.Get("Content-Type")) + fmt.Printf("`%s' に保存中\n", path.Base(downloadPath)) + fmt.Println("") + responseGet, err := http.Get(downloadPath) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(ExitAbort) + } + defer responseGet.Body.Close() + + file, err := os.Create(path.Base(downloadPath)) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(ExitAbort) + } + defer file.Close() + io.Copy(file, responseGet.Body) +} From 156204c1d770ee9b9309141ce39522285f6cce34 Mon Sep 17 00:00:00 2001 From: tokunagawataru Date: Sun, 1 Jul 2018 18:41:03 +0900 Subject: [PATCH 4/8] =?UTF-8?q?Range=E3=82=A2=E3=82=AF=E3=82=BB=E3=82=B9?= =?UTF-8?q?=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai3-2/tokunaga/main.go | 85 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/kadai3-2/tokunaga/main.go b/kadai3-2/tokunaga/main.go index e88adc5..19ecea9 100644 --- a/kadai3-2/tokunaga/main.go +++ b/kadai3-2/tokunaga/main.go @@ -7,6 +7,7 @@ import ( "net/http" "os" "path" + "runtime" "time" ) @@ -27,20 +28,81 @@ func main() { t := time.Now() fmt.Printf("--%s-- %s\n", t.Format(timeLayout), downloadPath) fmt.Print("HTTP による接続要求を送信しました、応答を待っています...") + + // head request responseHead, err := http.Head(downloadPath) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(ExitAbort) } + // response info + acceptRanges := responseHead.Header.Get("Accept-Ranges") statusCode := responseHead.StatusCode + fileSize := responseHead.ContentLength + contentType := responseHead.Header.Get("Content-Type") + fmt.Printf("%d %s\n", statusCode, http.StatusText(statusCode)) if responseHead.StatusCode != 200 { fmt.Fprintln(os.Stderr, http.StatusText(responseHead.StatusCode)) os.Exit(ExitAbort) } - fmt.Printf("長さ: %d [%s]\n", responseHead.ContentLength, responseHead.Header.Get("Content-Type")) + fmt.Printf("長さ: %d [%s]\n", fileSize, contentType) fmt.Printf("`%s' に保存中\n", path.Base(downloadPath)) fmt.Println("") + + if acceptRanges == "" { + singleDownload(downloadPath) + } else { + splitNum := runtime.NumCPU() + splitBytes := splitByteSize(fileSize, int64(splitNum)) + ranges := formatRange(splitBytes) + createFileMap := map[int]string{} + for no, rangeValue := range ranges { + req, _ := http.NewRequest("GET", downloadPath, nil) + req.Header.Set("RANGE", rangeValue) + + client := new(http.Client) + resp, err := client.Do(req) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(ExitAbort) + } + //defer resp.Body.Close() + createFileName := fmt.Sprintf("%s_%s", path.Base(downloadPath), rangeValue) + file, err := os.Create(createFileName) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(ExitAbort) + } + //defer file.Close() + createFileMap[no] = createFileName + io.Copy(file, resp.Body) + } + originFile, err := os.Create(path.Base(downloadPath)) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(ExitAbort) + } + defer originFile.Close() + for i := 0; i < splitNum; i++ { + splitFile, err := os.Open(createFileMap[i]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(ExitAbort) + } + io.Copy(originFile, splitFile) + splitFile.Close() + if err := os.Remove(createFileMap[i]); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(ExitAbort) + } + } + } + fmt.Printf("`%s' に保存完了\n", path.Base(downloadPath)) + os.Exit(ExitOK) +} + +func singleDownload(downloadPath string) { responseGet, err := http.Get(downloadPath) if err != nil { fmt.Fprintln(os.Stderr, err) @@ -56,3 +118,24 @@ func main() { defer file.Close() io.Copy(file, responseGet.Body) } + +func splitByteSize(byteSize int64, splitNum int64) []int64 { + var response = make([]int64, splitNum) + rest := byteSize % splitNum // ファイルのサイズを分割数で割った余り + splitUnit := (byteSize - rest) / splitNum // 分割したファイルのサイズ + for i := int64(0); i < splitNum-1; i++ { + response[i] = splitUnit + } + response[splitNum-1] = splitUnit + rest + return response +} + +func formatRange(splitBytes []int64) []string { + var response []string + var bytePosition int64 + for _, bytes := range splitBytes { + response = append(response, fmt.Sprintf("bytes=%d-%d", bytePosition, bytePosition+bytes-1)) + bytePosition = bytePosition + bytes + } + return response +} From 4c910c73b7fa58d77258baa41f3f40d4520499c2 Mon Sep 17 00:00:00 2001 From: tokunagawataru Date: Mon, 2 Jul 2018 03:04:43 +0900 Subject: [PATCH 5/8] =?UTF-8?q?=E3=83=AA=E3=83=95=E3=82=A1=E3=82=AF?= =?UTF-8?q?=E3=82=BF=E3=83=AA=E3=83=B3=E3=82=B0(=E5=BD=B9=E5=89=B2?= =?UTF-8?q?=E3=81=94=E3=81=A8=E3=81=AB=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB?= =?UTF-8?q?=E5=88=86=E5=89=B2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai3-2/tokunaga/cmd/goget/main.go | 60 ++++++++++++ kadai3-2/tokunaga/file.go | 122 ++++++++++++++++++++++++ kadai3-2/tokunaga/format.go | 16 ++++ kadai3-2/tokunaga/main.go | 141 ---------------------------- 4 files changed, 198 insertions(+), 141 deletions(-) create mode 100644 kadai3-2/tokunaga/cmd/goget/main.go create mode 100644 kadai3-2/tokunaga/file.go create mode 100644 kadai3-2/tokunaga/format.go delete mode 100644 kadai3-2/tokunaga/main.go diff --git a/kadai3-2/tokunaga/cmd/goget/main.go b/kadai3-2/tokunaga/cmd/goget/main.go new file mode 100644 index 0000000..2a09385 --- /dev/null +++ b/kadai3-2/tokunaga/cmd/goget/main.go @@ -0,0 +1,60 @@ +package main + +import ( + "flag" + "fmt" + "net/http" + "os" + "time" + + "github.com/gopherdojo/dojo2/kadai3-2/tokunaga" +) + +const ( + ExitOK = iota + ExitAbort +) +const timeLayout = "2006-01-02 15:04:05" + +func main() { + flag.Parse() + if len(flag.Args()) != 1 { + fmt.Fprintln(os.Stderr, "You can only download one file at a time") + os.Exit(ExitAbort) + } + downloadPath := flag.Args()[0] + + t := time.Now() + fmt.Printf("--%s-- %s\n", t.Format(timeLayout), downloadPath) + fmt.Print("HTTP による接続要求を送信しました、応答を待っています...") + + // head request + responseHead, err := http.Head(downloadPath) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(ExitAbort) + } + // response info + acceptRanges := responseHead.Header.Get("Accept-Ranges") + statusCode := responseHead.StatusCode + fileSize := responseHead.ContentLength + contentType := responseHead.Header.Get("Content-Type") + + downloadFile := tokunaga.File{Uri: downloadPath, FileSize: fileSize} + fmt.Printf("%d %s\n", statusCode, http.StatusText(statusCode)) + if responseHead.StatusCode != 200 { + fmt.Fprintln(os.Stderr, http.StatusText(responseHead.StatusCode)) + os.Exit(ExitAbort) + } + fmt.Printf("長さ: %d [%s]\n", fileSize, contentType) + fmt.Printf("`%s' に保存中\n", downloadFile.Filename()) + fmt.Println("") + + if err := downloadFile.Download(acceptRanges); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(ExitAbort) + } + + fmt.Printf("`%s' に保存完了\n", downloadFile.Filename()) + os.Exit(ExitOK) +} diff --git a/kadai3-2/tokunaga/file.go b/kadai3-2/tokunaga/file.go new file mode 100644 index 0000000..c8ca94a --- /dev/null +++ b/kadai3-2/tokunaga/file.go @@ -0,0 +1,122 @@ +package tokunaga + +import ( + "fmt" + "io" + "net/http" + "os" + "path" + "runtime" +) + +type File struct { + Uri string + FileSize int64 +} + +// ダウンロードファイルのUriからファイル名を取得 +func (f File) Filename() string { + return path.Base(f.Uri) +} + +func (f File) Download(acceptRanges string) error { + if acceptRanges == "" { + return f.singleDownload() + } else { + return f.splitDownload() + } +} + +// ファイルを一括ダウンロード +func (f File) singleDownload() error { + responseGet, err := http.Get(f.Uri) + if err != nil { + return err + } + defer responseGet.Body.Close() + + file, err := os.Create(f.Filename()) + if err != nil { + return err + } + defer file.Close() + _, err = io.Copy(file, responseGet.Body) + if err != nil { + return err + } + return nil +} + +func (f File) splitDownload() error { + splitNum := runtime.NumCPU() + splitBytes := f.SplitByteSize(int64(splitNum)) + ranges := formatRange(splitBytes) + createFileMap := map[int]string{} + for no, rangeValue := range ranges { + f.rangeDownload(no, rangeValue, createFileMap) + } + if err := f.joinSplitFiles(createFileMap); err != nil { + return err + } + return nil +} + +func (f File) rangeDownload(fileNo int, rangeValue string, createFiles map[int]string) error { + req, _ := http.NewRequest("GET", f.Uri, nil) + req.Header.Set("RANGE", rangeValue) + + client := new(http.Client) + resp, err := client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + createFileName := fmt.Sprintf("%s_%s", f.Filename(), rangeValue) + file, err := os.Create(createFileName) + if err != nil { + return err + } + defer file.Close() + createFiles[fileNo] = createFileName + _, err = io.Copy(file, resp.Body) + if err != nil { + return err + } + return nil +} + +func (f File) joinSplitFiles(createFiles map[int]string) error { + originFile, err := os.Create(f.Filename()) + if err != nil { + return err + } + defer originFile.Close() + for i := 0; i < len(createFiles); i++ { + splitFile, err := os.Open(createFiles[i]) + if err != nil { + return err + } + _, err = io.Copy(originFile, splitFile) + if err != nil { + return err + } + splitFile.Close() + if err := os.Remove(createFiles[i]); err != nil { + return err + } + } + return nil +} + +// ファイルのバイト数と分割数から、分割ダウンロードするファイルの各バイト数の配列を返す +// SplitByteSize(1002, 8) -> [125, 125, 125, 125, 125, 125, 125, 127] +func (f File) SplitByteSize(splitNum int64) []int64 { + var response = make([]int64, splitNum) + rest := f.FileSize % splitNum // ファイルのサイズを分割数で割った余り + splitUnit := (f.FileSize - rest) / splitNum // 分割したファイルのサイズ + for i := int64(0); i < splitNum-1; i++ { + response[i] = splitUnit + } + response[splitNum-1] = splitUnit + rest + return response +} diff --git a/kadai3-2/tokunaga/format.go b/kadai3-2/tokunaga/format.go new file mode 100644 index 0000000..95c592a --- /dev/null +++ b/kadai3-2/tokunaga/format.go @@ -0,0 +1,16 @@ +package tokunaga + +import "fmt" + +// 分割ダウンロードするファイルの各バイト数の配列から、request headerのRANGEに設定する値の配列を返す +// [25 25 25 28] +// -> [bytes=0-25 bytes=26-51 bytes=52-77 bytes=78-103] +func formatRange(splitBytes []int64) []string { + var response []string + var bytePosition int64 + for _, bytes := range splitBytes { + response = append(response, fmt.Sprintf("bytes=%d-%d", bytePosition, bytePosition+bytes-1)) + bytePosition = bytePosition + bytes + } + return response +} diff --git a/kadai3-2/tokunaga/main.go b/kadai3-2/tokunaga/main.go deleted file mode 100644 index 19ecea9..0000000 --- a/kadai3-2/tokunaga/main.go +++ /dev/null @@ -1,141 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "io" - "net/http" - "os" - "path" - "runtime" - "time" -) - -const ( - ExitOK = iota - ExitAbort -) -const timeLayout = "2006-01-02 15:04:05" - -func main() { - flag.Parse() - if len(flag.Args()) != 1 { - fmt.Fprintln(os.Stderr, "You can only download one file at a time") - os.Exit(ExitAbort) - } - downloadPath := flag.Args()[0] - - t := time.Now() - fmt.Printf("--%s-- %s\n", t.Format(timeLayout), downloadPath) - fmt.Print("HTTP による接続要求を送信しました、応答を待っています...") - - // head request - responseHead, err := http.Head(downloadPath) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(ExitAbort) - } - // response info - acceptRanges := responseHead.Header.Get("Accept-Ranges") - statusCode := responseHead.StatusCode - fileSize := responseHead.ContentLength - contentType := responseHead.Header.Get("Content-Type") - - fmt.Printf("%d %s\n", statusCode, http.StatusText(statusCode)) - if responseHead.StatusCode != 200 { - fmt.Fprintln(os.Stderr, http.StatusText(responseHead.StatusCode)) - os.Exit(ExitAbort) - } - fmt.Printf("長さ: %d [%s]\n", fileSize, contentType) - fmt.Printf("`%s' に保存中\n", path.Base(downloadPath)) - fmt.Println("") - - if acceptRanges == "" { - singleDownload(downloadPath) - } else { - splitNum := runtime.NumCPU() - splitBytes := splitByteSize(fileSize, int64(splitNum)) - ranges := formatRange(splitBytes) - createFileMap := map[int]string{} - for no, rangeValue := range ranges { - req, _ := http.NewRequest("GET", downloadPath, nil) - req.Header.Set("RANGE", rangeValue) - - client := new(http.Client) - resp, err := client.Do(req) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(ExitAbort) - } - //defer resp.Body.Close() - createFileName := fmt.Sprintf("%s_%s", path.Base(downloadPath), rangeValue) - file, err := os.Create(createFileName) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(ExitAbort) - } - //defer file.Close() - createFileMap[no] = createFileName - io.Copy(file, resp.Body) - } - originFile, err := os.Create(path.Base(downloadPath)) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(ExitAbort) - } - defer originFile.Close() - for i := 0; i < splitNum; i++ { - splitFile, err := os.Open(createFileMap[i]) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(ExitAbort) - } - io.Copy(originFile, splitFile) - splitFile.Close() - if err := os.Remove(createFileMap[i]); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(ExitAbort) - } - } - } - fmt.Printf("`%s' に保存完了\n", path.Base(downloadPath)) - os.Exit(ExitOK) -} - -func singleDownload(downloadPath string) { - responseGet, err := http.Get(downloadPath) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(ExitAbort) - } - defer responseGet.Body.Close() - - file, err := os.Create(path.Base(downloadPath)) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(ExitAbort) - } - defer file.Close() - io.Copy(file, responseGet.Body) -} - -func splitByteSize(byteSize int64, splitNum int64) []int64 { - var response = make([]int64, splitNum) - rest := byteSize % splitNum // ファイルのサイズを分割数で割った余り - splitUnit := (byteSize - rest) / splitNum // 分割したファイルのサイズ - for i := int64(0); i < splitNum-1; i++ { - response[i] = splitUnit - } - response[splitNum-1] = splitUnit + rest - return response -} - -func formatRange(splitBytes []int64) []string { - var response []string - var bytePosition int64 - for _, bytes := range splitBytes { - response = append(response, fmt.Sprintf("bytes=%d-%d", bytePosition, bytePosition+bytes-1)) - bytePosition = bytePosition + bytes - } - return response -} From 1d25e7ff8c21ea5f46da442f54dd982b3b06627e Mon Sep 17 00:00:00 2001 From: tokunagawataru Date: Tue, 3 Jul 2018 00:57:08 +0900 Subject: [PATCH 6/8] =?UTF-8?q?=E5=88=86=E5=89=B2=E3=83=80=E3=82=A6?= =?UTF-8?q?=E3=83=B3=E3=83=AD=E3=83=BC=E3=83=89=E3=82=92gorutine=E3=81=AB?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai3-2/tokunaga/file.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/kadai3-2/tokunaga/file.go b/kadai3-2/tokunaga/file.go index c8ca94a..f7dcefd 100644 --- a/kadai3-2/tokunaga/file.go +++ b/kadai3-2/tokunaga/file.go @@ -7,6 +7,7 @@ import ( "os" "path" "runtime" + "sync" ) type File struct { @@ -19,6 +20,7 @@ func (f File) Filename() string { return path.Base(f.Uri) } +// acceptRangesによってダウンロード方法を切り替える func (f File) Download(acceptRanges string) error { if acceptRanges == "" { return f.singleDownload() @@ -47,21 +49,27 @@ func (f File) singleDownload() error { return nil } +// ファイルを分割ダウンロード func (f File) splitDownload() error { splitNum := runtime.NumCPU() splitBytes := f.SplitByteSize(int64(splitNum)) ranges := formatRange(splitBytes) createFileMap := map[int]string{} + + var wg sync.WaitGroup for no, rangeValue := range ranges { - f.rangeDownload(no, rangeValue, createFileMap) + wg.Add(1) + go f.rangeDownload(&wg, no, rangeValue, createFileMap) } + wg.Wait() if err := f.joinSplitFiles(createFileMap); err != nil { return err } return nil } -func (f File) rangeDownload(fileNo int, rangeValue string, createFiles map[int]string) error { +func (f File) rangeDownload(wg *sync.WaitGroup, fileNo int, rangeValue string, createFiles map[int]string) error { + defer wg.Done() req, _ := http.NewRequest("GET", f.Uri, nil) req.Header.Set("RANGE", rangeValue) @@ -85,6 +93,7 @@ func (f File) rangeDownload(fileNo int, rangeValue string, createFiles map[int]s return nil } +// 分割されたファイルを一つに結合させる func (f File) joinSplitFiles(createFiles map[int]string) error { originFile, err := os.Create(f.Filename()) if err != nil { From 722f173b2720f076fbc47b7ec0eb228a942d8448 Mon Sep 17 00:00:00 2001 From: tokunagawataru Date: Tue, 3 Jul 2018 01:35:39 +0900 Subject: [PATCH 7/8] =?UTF-8?q?errrorgroup=E3=82=92=E4=BD=BF=E3=81=A3?= =?UTF-8?q?=E3=81=A6gorutine=E3=81=AE=E3=82=A8=E3=83=A9=E3=83=BC=E3=82=92?= =?UTF-8?q?=E3=82=AD=E3=83=A3=E3=83=83=E3=83=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai3-2/tokunaga/file.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kadai3-2/tokunaga/file.go b/kadai3-2/tokunaga/file.go index f7dcefd..384efc4 100644 --- a/kadai3-2/tokunaga/file.go +++ b/kadai3-2/tokunaga/file.go @@ -8,6 +8,8 @@ import ( "path" "runtime" "sync" + + "golang.org/x/sync/errgroup" ) type File struct { @@ -56,10 +58,16 @@ func (f File) splitDownload() error { ranges := formatRange(splitBytes) createFileMap := map[int]string{} + var eg errgroup.Group var wg sync.WaitGroup for no, rangeValue := range ranges { wg.Add(1) - go f.rangeDownload(&wg, no, rangeValue, createFileMap) + eg.Go(func() error { + return f.rangeDownload(&wg, no, rangeValue, createFileMap) + }) + } + if err := eg.Wait(); err != nil { + return err } wg.Wait() if err := f.joinSplitFiles(createFileMap); err != nil { From 41d7cd53246dc9374a839987b4c80368c176c328 Mon Sep 17 00:00:00 2001 From: tokunagawataru Date: Wed, 4 Jul 2018 02:43:39 +0900 Subject: [PATCH 8/8] =?UTF-8?q?rangeDownload=E3=81=AB=E5=90=8C=E3=81=98?= =?UTF-8?q?=E5=BC=95=E6=95=B0=E3=81=8C=E4=B8=8E=E3=81=88=E3=82=89=E3=82=8C?= =?UTF-8?q?=E7=B6=9A=E3=81=91=E3=82=8B=E4=B8=8D=E5=85=B7=E5=90=88=E3=82=92?= =?UTF-8?q?=E8=A7=A3=E6=B6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai3-2/tokunaga/file.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/kadai3-2/tokunaga/file.go b/kadai3-2/tokunaga/file.go index 384efc4..578cfb0 100644 --- a/kadai3-2/tokunaga/file.go +++ b/kadai3-2/tokunaga/file.go @@ -7,8 +7,6 @@ import ( "os" "path" "runtime" - "sync" - "golang.org/x/sync/errgroup" ) @@ -58,26 +56,24 @@ func (f File) splitDownload() error { ranges := formatRange(splitBytes) createFileMap := map[int]string{} - var eg errgroup.Group - var wg sync.WaitGroup + eg := errgroup.Group{} for no, rangeValue := range ranges { - wg.Add(1) + index := no + value := rangeValue eg.Go(func() error { - return f.rangeDownload(&wg, no, rangeValue, createFileMap) + return f.rangeDownload(index, value, createFileMap) }) } if err := eg.Wait(); err != nil { return err } - wg.Wait() if err := f.joinSplitFiles(createFileMap); err != nil { return err } return nil } -func (f File) rangeDownload(wg *sync.WaitGroup, fileNo int, rangeValue string, createFiles map[int]string) error { - defer wg.Done() +func (f File) rangeDownload(fileNo int, rangeValue string, createFiles map[int]string) error { req, _ := http.NewRequest("GET", f.Uri, nil) req.Header.Set("RANGE", rangeValue)