上次面试时,面试官要求手写代码,题目:
1. 多个文件中存在着一串用空格隔开的数字
2. 读取文件中的数字,计算多个文件的平方和
3. 使用多协程方式
代码:
package main
import (
"flag"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
"time"
)
func power(num string) int {
n, err := strconv.Atoi(num)
if err != nil {
fmt.Printf("something is wrong, the string:%s\n", num)
return 0
}
return n * n
}
//文件中的数字已空格隔开
func readFileAndCalc(file string) []int {
result := make([]int, 0)
bytes, _ := ioutil.ReadFile(file)
//若不去除,可能会出现末尾字符问题
str := strings.Replace(string(bytes), "\n", "", -1)
nums := strings.Split(str, " ")
for _, num := range nums {
result = append(result, power(num))
}
fmt.Printf("File:%s result:%v\n", file, result)
return result
}
func comparelCalc(pathDir string) error {
f, err := os.Stat(pathDir)
if err != nil {
return err
} else if !f.IsDir() {
return fmt.Errorf("path:%v is not the Dirent", pathDir)
}
result := 0
files, _ := ioutil.ReadDir(pathDir)
ch := make(chan []int, len(files)) //带缓存区的int[] Channel
for _, f := range files {
//非目录
if !f.IsDir() {
file := fmt.Sprintf("%s/%s", pathDir, f.Name()) //file完整路径
go func(f string) {
res := readFileAndCalc(f)
ch <- res //结果通知
}(file)
}
}
ov := make(chan struct{}, 0)
go func() {
i := 0
for nums := range ch {
for _, num := range nums {
result = result + num
}
i++
if i == len(files) {
ov <- struct{}{}
}
}
}()
//超过两分钟,没有结果 ---> 结束
select {
case <-time.After(120 * time.Second):
close(ch)
return fmt.Errorf("time out")
case <-ov:
fmt.Printf("all file result = %d\n", result)
close(ch)
}
return nil
}
//test
func main() {
path := flag.String("path", "/home/test/test", "Input your path")
if err := comparelCalc(*path); err != nil {
fmt.Println(err)
}
}
结果验证:
# ls /home/test/test
ddd dmm mm
# go run comparelCalc.go -path=/home/test/test
File:/home/test/test/ddd result:[1 9 16]
File:/home/test/test/mm result:[1 9 25 25 9 25 9 64 121 484 1936 484 14884 8100]
File:/home/test/test/dmm result:[1 9 25 25 484]
all file result = 26746