-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
121 lines (110 loc) · 2.63 KB
/
main.go
File metadata and controls
121 lines (110 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package main
import (
"flag"
"fmt"
"io/ioutil"
"net/http"
"os"
"regexp"
"strings"
"sync"
)
func main() {
data := getDataFromStdin()
arr := dataToArray(string(data))
flagType := getFlagType()
var results = make(chan int, len(arr))
k := 3
createWorkerPool(arr, k, results, flagType)
close(results)
sum := 0
for result := range results {
sum += result
}
fmt.Println("Total:", sum)
}
func getFlagType() string {
typeData := flag.String("type", "", "a type")
flag.Parse()
if *typeData != "url" && *typeData != "file" {
fmt.Println("invalid flag: '--type url || file'")
os.Exit(1)
}
return *typeData
}
func getDataFromStdin() []byte {
bytes, _ := ioutil.ReadAll(os.Stdin)
return bytes
}
func dataToArray(data string) []string {
return strings.Split(data, "\n")
}
func getUrlData(url string) (string, error) {
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
}
func getFileData(path string) (string, error) {
d, err := ioutil.ReadFile(path)
if err != nil {
return "", err
}
return string(d), nil
}
func worker(path string, results chan<- int, wg *sync.WaitGroup, flagType string) {
var data string
var err error
switch flagType {
case "url":
data, err = getUrlData(path)
case "file":
data, err = getFileData(path)
}
if err != nil {
fmt.Println("Error in", path+":", err)
wg.Done()
return
}
searchArr := searchWords("Go", data)
wordLen := len(searchArr)
fmt.Println("Count for", path+":", wordLen)
results <- wordLen
wg.Done()
}
func createWorkerPoolLimit(start int, finish int, list []string, results chan int, flagType string) {
var wg sync.WaitGroup
for i := start; i < finish; i++ {
if len(list)-1 >= i && list[i] != "" {
wg.Add(1)
go worker(list[i], results, &wg, flagType)
}
}
wg.Wait()
}
func createWorkerPool(list []string, k int, results chan int, flagType string) {
listLen := len(list)
if listLen > k {
for i := 0; i < listLen; i += k {
createWorkerPoolLimit(i, i+k, list, results, flagType)
}
} else {
createWorkerPoolLimit(0, listLen, list, results, flagType)
}
}
func searchWords(word string, data string) []string {
reg := regexp.MustCompile(`\b` + word + `\b[’]?`) // в идеале `\bword\b(?![’])`, но поиск в go regexp не поддерживается
arr := reg.FindAllString(data, -1)
for i, item := range arr {
if item == word+"’" {
arr = append(arr[:i], arr[i+1:]...)
}
}
return arr
}