func (i *IPAddressPoller) Run(stopCh <-chan struct{}) error {
	if err := i.poll(); err != nil {
		log.Printf("Error polling for IP: %v", err)
	}
	for {
		select {
		case <-time.After(i.pollInterval):
			if err := i.poll(); err != nil {
				log.Printf("Error polling for IP: %v", err)
			}
		case <-stopCh:
			return nil
		}
	}
}
Run() starts the main loop for the poller.
package sync
import (
	"context"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"strings"
	"time"
	"golang.org/x/net/html"
)
var webCheck = []string{
	"http://checkip.dyndns.org/",
	"http://ipdetect.dnspark.com/",
	"http://dns.loopia.se/checkip/checkip.php",
}
type IPAddressPoller struct {
	channels     []chan string
	pollInterval time.Duration
}
func NewIPAddressPoller(pollInterval time.Duration) *IPAddressPoller {
	return &IPAddressPoller{
		pollInterval: pollInterval,
	}
}
func (p *IPAddressPoller) Channel() <-chan string {
	c := make(chan string, 1)
	p.channels = append(p.channels, c)
	return c
}
func (p *IPAddressPoller) poll() error {
	urls := make([]string, len(webCheck))
	copy(urls, webCheck)
	for i := range urls {
		j := rand.Intn(i + 1)
		urls[i], urls[j] = urls[j], urls[i]
	}
	var lastErr error
	for i := range urls {
		ip, err := request(urls[i])
		if err != nil {
			lastErr = err
			continue
		}
		for _, c := range p.channels {
			select {
			case c <- ip:
			default:
			}
		}
		return nil
	}
	return fmt.Errorf("Could not obtain IP address: %v", lastErr)
}
func request(url string) (string, error) {
	req, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return "", err
	}
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	req = req.WithContext(ctx)
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return "", err
	}
	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("Got status code from %q: %d", url, resp.StatusCode)
	}
	z := html.NewTokenizer(resp.Body)
	for {
		tt := z.Next()
		switch tt {
		case html.ErrorToken:
			return "", z.Err()
		case html.TextToken:
			text := strings.Trim(string(z.Text()), " \n\t")
			if text != "" {
				ip := ""
				fmt.Sscanf(text, "Current IP Address: %s", &ip)
				if ip != "" {
					return strings.Trim(ip, " \n\t"), nil
				}
			}
		}
	}
}