1. 程式人生 > 實用技巧 >go 內網IP及外網IP獲取

go 內網IP及外網IP獲取

流傳的go版本內網獲取都不準確,所以想到之前看到的python版本,通過擬一個UDP連線來獲取

package main

import (
	"errors"
	"fmt"
	"io"
	"net"
	"net/http"
	"strings"
)

func main() {
	fmt.Println(GetExternalIP())
	fmt.Println(GetInternalIP())
}

func GetInternalIP() (string, error) {
	// 思路來自於Python版本的內網IP獲取,其他版本不準確
	conn, err := net.Dial("udp", "8.8.8.8:80")
	if err != nil {
		return "", errors.New("internal IP fetch failed, detail:" + err.Error())
	}
	defer conn.Close()

	// udp 面向無連線,所以這些東西只在你本地搗鼓
	res := conn.LocalAddr().String()
	res = strings.Split(res, ":")[0]
	return res, nil
}

func GetExternalIP() (string, error) {
	// 有很多類似網站提供這種服務,這是我知道且正在用的
	// 備用:https://myexternalip.com/raw (cip.cc 應該是夠快了,我連手機熱點的時候不太穩,其他自己查)
	response, err := http.Get("http://ip.cip.cc")
	if err != nil {
		return "", errors.New("external IP fetch failed, detail:" + err.Error())
	}

	defer response.Body.Close()
	res := ""

	// 類似的API應當返回一個純淨的IP地址
	for {
		tmp := make([]byte, 32)
		n, err := response.Body.Read(tmp)
		if err != nil {
			if err != io.EOF {
				return "", errors.New("external IP fetch failed, detail:" + err.Error())
			}
			res += string(tmp[:n])
			break
		}
		res += string(tmp[:n])
	}

	return strings.TrimSpace(res), nil
}