Go言語初体験
11340 ワード
言語設計の争いに対して、唯一覚えなければならないのは、CをC++に変えると、Cは消えてしまうということだ.
Goは軽量級の簡潔な同時サポート言語で、探求的な個人プロジェクトに使用することができます.これは私がこの言語を学びたい主な原因です.プログラミングの経験がある人にとって、新しい言語を学ぶ方法は、まず言語の特性を概説し、それから中規模のプログラムを作成し、できるだけ大部分の重要な特性に運用することです.
次のプログラムは、1つのディレクトリの下にあるすべてのファイルまたはディレクトリのサイズを計算するために使用されます.
Goは軽量級の簡潔な同時サポート言語で、探求的な個人プロジェクトに使用することができます.これは私がこの言語を学びたい主な原因です.プログラミングの経験がある人にとって、新しい言語を学ぶ方法は、まず言語の特性を概説し、それから中規模のプログラムを作成し、できるだけ大部分の重要な特性に運用することです.
次のプログラムは、1つのディレクトリの下にあるすべてのファイルまたはディレクトリのサイズを計算するために使用されます.
package main
import (
"fmt"
"time"
"os"
"log"
)
type ShortFileInfo struct {
fileName string
size int64
}
func (fileInfo *ShortFileInfo) Desc() string {
return fmt.Sprintf("{%s:%d}", fileInfo.fileName, fileInfo.size)
}
func produceFiles(dirName string) []os.FileInfo {
path, err := os.Open(dirName)
if err != nil {
log.Fatal(err)
}
defer path.Close()
fileInfos, err := path.Readdir(0);
if err != nil {
log.Fatal(err)
}
return fileInfos;
}
func procFile(fileInfo os.FileInfo, baseDirName string, channelBuffer chan ShortFileInfo) {
var filesize int64
fileName := fileInfo.Name()
if fileInfo.IsDir() {
filesize = totalFilesizeInDir(fileInfo, baseDirName)
} else {
filesize = fileInfo.Size()
}
shortFileInfo := ShortFileInfo{fileName, filesize};
fmt.Println(time.Now().String() + " store: " + shortFileInfo.Desc())
channelBuffer <- shortFileInfo
}
func totalFilesizeInDir(fileInfo os.FileInfo, baseDirName string) int64 {
var filesize int64 = 0
fileInfos := produceFiles(baseDirName + "\\" + fileInfo.Name())
for _, subfileInfo := range fileInfos {
if subfileInfo.IsDir() {
filesize += totalFilesizeInDir(subfileInfo, baseDirName + "\\" + fileInfo.Name())
} else {
filesize += subfileInfo.Size()
}
}
return filesize
}
func sleep(ns int) {
time.Sleep(time.Duration(time.Second)*time.Duration(ns))
}
const (
B int64 = 1
KB int64 = 1024
MB int64 = 1024*1024
GB int64 = 1024*1024*1024
TB int64 = 1024*1024*1024*1024
)
const formatF string = "%8.4f"
func readableSize(sizeInBytes int64) string {
switch {
case B <= sizeInBytes && sizeInBytes < KB:
return fmt.Sprintf("%dB", sizeInBytes)
case KB <= sizeInBytes && sizeInBytes < MB:
return fmt.Sprintf(formatF+"KB", float64(sizeInBytes)/float64(KB))
case MB <= sizeInBytes && sizeInBytes < GB:
return fmt.Sprintf(formatF+"MB", float64(sizeInBytes)/float64(MB))
case GB <= sizeInBytes && sizeInBytes < TB:
return fmt.Sprintf(formatF+"GB", float64(sizeInBytes)/float64(GB))
case TB <= sizeInBytes:
return fmt.Sprintf(formatF+"TB", float64(sizeInBytes)/float64(TB))
default:
return "0"
}
}
func main() {
baseDirName := "C:\\Users\\qin.shuq\\Desktop"
fileList := produceFiles(baseDirName)
fileNumber := len(fileList)
channelBuffer := make(chan ShortFileInfo, fileNumber)
fileInfoMap := make(map[string] int64, fileNumber)
for _, fileInfo := range fileList {
go procFile(fileInfo, baseDirName, channelBuffer)
}
for count := 0 ; count <= fileNumber ; {
select {
case fileInfo := <- channelBuffer:
fmt.Println(time.Now().String() + " fetch: " + fileInfo.Desc())
fileInfoMap[fileInfo.fileName] = fileInfo.size
count++
default:
if count == fileNumber {
close(channelBuffer)
}
fmt.Println("Waiting for data ...")
sleep(2)
}
}
var totalSize int64
totalSize = 0
for _ , filesize := range fileInfoMap {
totalSize += filesize
}
fmt.Printf("Total size in %s:%dB %s", baseDirName , totalSize, readableSize(totalSize));
}