5月 16, 2024

Golang 初體驗 - 網址檢測工具

這篇沒什麼技術價值,只是很久之前跟別人聊天的時候,碰到他正在寫 golang,雖然已經是個有一段時間的程式語言了,但後來也就看看而已

接著大約半年前,剛好試驗性的跟他玩了一下 golang build 成 exe 的檔案,所以 golang 就被我列入了預計摸摸看的項目


然後過了半年後,剛好有個小小的功能要使用,其實曾經用 PHP 寫過了,只是想說前幾天不小心裝了 golang 的環境,然後不如趁這次機會寫寫看,以後也可以把檔案分出去用

再次提醒,本篇沒技術價值,就是試驗品

## 目標的練習功能

  • 基本輸入輸出
  • 基本迴圈使用
  • 基本的 func 定義、呼叫
  • 基本的讀寫檔案
  • 基本的非同步呼叫
  • 基本的 http request
  • 各種基本的操作跟語法

## 執行目的需求

    程式執行後,請求輸入要引入的檔案名稱,接著針對檔案的內容去拆寫每一行,每一行的資料是一個域名(也就是自己網站),然後我有在網站上放置一個檢測用的檔案

  • check_path = 放置的目錄
  • check_string = 測試檔案的內容
接著只要針對每個網域中的檢測檔案去呼叫,並確認拿到的結果是不是自己設定的資料即可,如果網址已經不存在或者有異常就不會紀錄,或可以排除
延伸使用可以改寫成如果網址掛掉或出問題時才紀錄,然後回傳並接著後續的通報處理等,但這不是我目前的目的所以先不贅述

package main

import (
    "errors"
    "fmt"
    "io"
    "log"
    "net/http"
    "os"
    "strings"
    "sync"
    "time"
)

func main() {
    const check_path = "__CHECK_URL__"
    var input_filename string
    var output_filename string
    var test_string string = "__CHECK_STR__"
    for isContinue := true; isContinue; {
        fmt.Print("Please enter filename: ")
        fmt.Scanln(&input_filename)
        if input_filename != "" {
            isContinue = false
        }
    }
    if input_filename == "q" {
        os.Exit(0)
    }
    var content string = readFileContent(input_filename)
    if content != "" {
        var arr = explode("\n", content)
        var wg sync.WaitGroup
        fmt.Println("Start checking")
        var exist_list []string
        for i := 0; i < len(arr); i++ {
            wg.Add(1)
            go func(i int) {
                defer wg.Done()
                url := buildUrl(arr[i], check_path)
                response, success := curl_get(url)
                if success && response == test_string {
                    exist_list = append(exist_list, arr[i])
                }
            }(i)
        }
        wg.Wait()
        if len(exist_list) > 0 {
            fmt.Println("You have " + fmt.Sprint(len(exist_list)) + " exist domain ..")
            fmt.Print("Enter file to save result(default: result.txt) : ")
            fmt.Scan(&output_filename)
            if output_filename == "" {
                output_filename = "result.txt"
            }
            var output_file, _err = os.OpenFile(output_filename, os.O_RDWR|os.O_CREATE, 0755)
            if _err != nil {
                log.Fatal("Error open file: ", _err)
            }
            defer output_file.Close()
            for i := 0; i < len(exist_list); i++ {
                _, err := output_file.WriteString(exist_list[i] + "\n")
                if err != nil {
                    log.Fatal("Error write file: ", err)
                }
            }
        }
        fmt.Println("Complete checking task")
    }
}

func buildUrl(url string, path string) string {
    url = checkAndFixHttps(url)
    url = strings.TrimRight(url, "/") + "/" + strings.TrimLeft(path, "/")
    return url
}

func curl_get(url string) (string, bool) {
    var response *http.Response
    var http_err error
    var httpInst = http.Client{
        Timeout: 2 * time.Second,
    }
    response, http_err = httpInst.Get(url)
    if http_err != nil {
        return "", false
    }

    defer response.Body.Close()
    if response.StatusCode != http.StatusOK {
        return "", false
    }
    var result, err = io.ReadAll(response.Body)
    if err != nil {
        return "", false
    }
    return string(result), true

}

func readFileContent(filename string) string {
    dat, err := os.ReadFile(filename)
    if err != nil && errors.Is(err, os.ErrNotExist) {
        log.Fatal("File not exist: " + filename)
        return ""
    } else if err != nil {
        log.Fatal("Read error: ", err)
        return ""
    }
    return string(dat)
}

func explode(separator string, str string, limit ...int) []string {
    sep_limit := 0
    if len(limit) > 0 {
        sep_limit = limit[0]
    }
    var full_split_result = strings.Split(str, separator)
    if sep_limit > 0 {
        result := full_split_result[0 : sep_limit-1]
        return result
    } else {
        return full_split_result
    }
}

func checkAndFixHttps(url string) string {
    if strings.HasPrefix(url, "https://") {
        return url
    } else if strings.HasPrefix(url, "http://") {
        return strings.Replace(url, "http://", "https://", 1)
    } else {
        return "https://" + url
    }
}

總算解決了一個小小的 Side project 測試...

沒有留言:

張貼留言