package cssmerger import ( "fmt" "io" "log" "os" "path/filepath" ) // Первый аргумент - путь до директории, с которой будет начат рекурсивный поиск и склейка css файлов. // Второй аргумент - путь к мыходному файлу. // Третий аргумент - список имен файлов/директорий, которые надо проигнорировать. Если такого списка нет, стоит указать nil func Merge(root, output string, skipfiles []string) error { outFile, err := os.Create(output) if err != nil { log.Fatal("Output file create error") } defer outFile.Close() // Передаваемая вторым аргументам функция должна быть определенной сигнатуры (такой как тут) if err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { // Не работаем с файлам из skipfiles if stringSliceContains(skipfiles, info.Name()) { if !info.IsDir() { // Если это не директория, то сигнализируем, что работа с файлом завершена return nil } else { // Если это директория, то в нее не заходим return filepath.SkipDir } } // Работа с каждым css файлом if !info.IsDir() && filepath.Ext(info.Name()) == ".css" { file, err := os.Open(path) if err != nil { fmt.Printf("Failed to open %s file\n", path) return nil } data, err := io.ReadAll(file) if err != nil { fmt.Printf("Failed to read %s file\n", path) return nil } file.Close() _, err = writeFile(outFile, data) if err != nil { fmt.Printf("Failed to write in %s file\n", path) } } // Если возвращаемое значение nil, то обход продолжится return nil }); err != nil { return err } return nil } func writeFile(file *os.File, data []byte) (n int, err error) { bcount := 0 for _, char := range data { if char == '\n' || char == ' ' { continue } n, err := file.Write([]byte{byte(char)}) if err != nil { return n, err } bcount += n } return n, nil } // Проверяет есть ли строка в срезе строк func stringSliceContains(s []string, e string) bool { for _, a := range s { if a == e { return true } } return false }