对于语言设计之争, 唯一需要牢记的一句话是: 如果把 C 变成 C++, 那么 C 就消失了。
Go 是一个轻量级的简洁的支持并发的语言, 可以用于探索性个人项目, 这是我想学这门语言的主要原因。 对于有一定编程经验的人来说, 学习一种新语言的方式是, 先概览下语言特性, 然后编写一个中等规模的程序, 尽可能地运用到大部分重要特性。
下面的程序用于计算一个目录下所有文件或目录的大小。
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)); }