案例01:拼接两个目录路径
package main
import (
"fmt"
"os"
"path"
)
func main() {
dirPath := "D:/data/opensca/sim/source/gitee/java"
files, _ := os.ReadDir(dirPath)
for _, f := range files {
if f.IsDir() {
tmpDir := path.Join(dirPath, f.Name())
fmt.Println(tmpDir)
}
}
}
案例02:filpath.Glob获取当前目录下的所有文件
package main
import (
"fmt"
"path/filepath"
)
func main() {
// 获取当前目录下的所有文件
files, _ := filepath.Glob("*")
fmt.Println(files)
}
案例03:os.ReadDir读取特定目录
package main
import (
"fmt"
"os"
)
func main() {
dirPath := "D:/data/opensca/sim/source/gitee/java"
files, _ := os.ReadDir(dirPath)
for _, f := range files {
fmt.Println(f.Name(), f.IsDir())
}
}
案例04:filepath.Walk遍历目录树
Walk函数会遍历root指定的目录下的文件树,对每一个该文件树中的目录和文件都会调用walkFn,包括root自身。所有访问文件/目录时遇到的错误都会传递给walkFn过滤。文件是按词法顺序遍历的,这让输出更漂亮,但也导致处理非常大的目录时效率会降低。Walk函数不会遍历文件树中的符号链接(快捷方式)文件包含的路径。
package main
import (
"fmt"
"os"
"path/filepath"
)
func handleFiles(path string, info os.FileInfo, err error) error {
fmt.Println("路径:", path)
fmt.Println("是否为目录:", info.IsDir())
fmt.Println("文件名:", info.Name())
fmt.Println("大小:", info.Size())
fmt.Println("权限:", info.Mode())
fmt.Println("修改时间:", info.ModTime())
fmt.Println()
return err
}
func main() {
srcFile := "D:/projects/zdpgo_tar"
filepath.Walk(srcFile, handleFiles)
}
案例05:获取文件MD5值
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"os"
)
func GetFileMd5(filePath string) (string, error) {
file, err := os.Open(filePath)
if err != nil {
return "", err
}
hash := md5.New()
_, _ = io.Copy(hash, file)
return hex.EncodeToString(hash.Sum(nil)), nil
}
func main() {
v, _ := GetFileMd5("test/build.sh")
fmt.Println(v)
}
案例06:判断存在/文件/目录
package main
import (
"fmt"
"os"
)
func main() {
dirPath := "D:/data/github/java"
fmt.Println("是否存在:", IsExists(dirPath))
fmt.Println("是否为目录:", IsDir(dirPath))
fmt.Println("是否为文件:", IsFile(dirPath))
}
// IsExists 判断是否存在
func IsExists(path string) bool {
_, err := os.Stat(path)
return err == nil
}
// IsDir 判断所给路径是否为文件夹
func IsDir(path string) bool {
s, err := os.Stat(path)
if err != nil {
return false
}
return s.IsDir()
}
// IsFile 判断所给路径是否为文件
func IsFile(path string) bool {
s, err := os.Stat(path)
if err != nil {
return false
}
return !s.IsDir()
}
案例07:获取文件夹名
package main
import (
"fmt"
"path/filepath"
)
func main() {
dir := "D:/a/b/c"
// 文件文件夹名
base := filepath.Base(dir)
fmt.Println(base)
// 获取父目录
dir1 := filepath.Dir(dir)
fmt.Println(dir1)
}
案例08:使用缓冲写文件
package main
import (
"bufio"
"log"
"os"
)
var lines = []string{
"Go",
"is",
"the",
"best",
"programming",
"language",
"in",
"the",
"world",
}
func main() {
// 创建文件
f, err := os.Create("file.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
// 创建缓冲
buffer := bufio.NewWriter(f)
// 写数据
for _, line := range lines {
_, err = buffer.WriteString(line + "\n")
if err != nil {
log.Fatal(err)
}
}
// 刷新数据
if err = buffer.Flush(); err != nil {
log.Fatal(err)
}
}
案例09:并发写文件
package main
import (
"bufio"
"fmt"
"os"
"runtime"
"runtime/debug"
"sync"
)
func main() {
// 创建文件
txtFile, err := os.OpenFile("55555.txt", os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777) // O_TRUNC 清空重写
if err != nil {
fmt.Println("WriteDataToTxt os.OpenFile() err:", err)
return
}
defer txtFile.Close()
// 创建buffer
bufWriter := bufio.NewWriter(txtFile)
var wg sync.WaitGroup
limitChan := make(chan struct{}, runtime.GOMAXPROCS(runtime.NumCPU())) // 最大并发协程数
var mutex sync.Mutex
for i := 0; i < 10000; i++ { // 写1w行测试
limitChan
wg.Add(1)
go func(j int) {
// 捕获错误
defer func() {
if e := recover(); e != nil {
fmt.Printf("WriteDataToTxt panic: %v,stack: %s\n", e, debug.Stack())
}
wg.Done()
}()
// 模拟业务逻辑:先整合所有数据,然后再统一写WriteString()
strId := fmt.Sprintf("%v", j)
strName := fmt.Sprintf(" user_%v", j)
strScore := fmt.Sprintf(" %d", j*10)
mutex.Lock() // 要加锁/解锁,否则 bufWriter.WriteString 写入数据有问题
_, err = bufWriter.WriteString(strId + strName + strScore + "\n")
if err != nil {
fmt.Printf("WriteDataToTxt WriteString err: %v\n", err)
return
}
mutex.Unlock()
}(i)
}
wg.Wait()
// 刷入磁盘,可以多次刷
bufWriter.Flush()
bufWriter.Flush()
bufWriter.Flush()
}
领取专属 10元无门槛券
私享最新 技术干货