package main
import (
"bufio"
"fmt"
"log"
"net/http"
"os"
"sync"
)
func main() {
// Check if the correct number of arguments is passed
if len(os.Args) < 2 {
fmt.Println("Usage: go run main.go <input_file>")
return
}
// Get the input file from command line arguments
inputFile := os.Args[1]
// Open the input file
file, err := os.Open(inputFile)
if err != nil {
log.Fatalf("Failed to open file: %v\n", err)
}
defer file.Close()
// Create output files for works and failed URLs
worksFile, err := os.Create("works.txt")
if err != nil {
log.Fatalf("Failed to create works.txt: %v\n", err)
}
defer worksFile.Close()
failedFile, err := os.Create("failed.txt")
if err != nil {
log.Fatalf("Failed to create failed.txt: %v\n", err)
}
defer failedFile.Close()
// Create a scanner to read the input file line by line
scanner := bufio.NewScanner(file)
// Channels for results
worksChan := make(chan string)
failedChan := make(chan string)
// WaitGroup to wait for all goroutines to finish
var wg sync.WaitGroup
// Worker function to check URL
checkURL := func(url string) {
defer wg.Done() // Decrease the counter when the goroutine completes
// Check if the URL is accessible
resp, err := http.Get(url)
if err != nil || resp.StatusCode != http.StatusOK {
// If there's an error or the status is not 200 OK, send to failed channel
failedChan <- url
} else {
// If the URL is successful, send to works channel
worksChan <- url
}
// Close the response body if the request was successful
if resp != nil {
resp.Body.Close()
}
}
// Goroutine to handle writing to works.txt
go func() {
for url := range worksChan {
worksFile.WriteString(url + "\n")
}
}()
// Goroutine to handle writing to failed.txt
go func() {
for url := range failedChan {
failedFile.WriteString(url + "\n")
}
}()
// Iterate through each line (URL) in the file and start a goroutine for each
for scanner.Scan() {
url := scanner.Text()
wg.Add(1) // Increase the counter for each goroutine
go checkURL(url)
}
// Wait for all goroutines to finish
wg.Wait()
// Close the channels once all URLs have been processed
close(worksChan)
close(failedChan)
// Check for any scanner errors
if err := scanner.Err(); err != nil {
log.Fatalf("Error reading file: %v\n", err)
}
fmt.Println("URL check completed. See works.txt and failed.txt for results.")
}