Go语言初尝


        对于语言设计之争, 唯一需要牢记的一句话是: 如果把 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));



} 

 

 
  


               

 

你可能感兴趣的:(go语言)