package main
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "os"
+ "sync"
+ "time"
+
+ "golang.org/x/net/html"
+)
+
+
+func fetchTitle(ctx context.Context, url string) (string, error) {
+ startTime := time.Now()
+ req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
+ if err != nil {
+ return "", err
+ }
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return "", err
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != http.StatusOK {
+ return "", fmt.Errorf("bad status: %s", resp.Status)
+ }
+
+ doc, err := html.Parse(resp.Body)
+ if err != nil {
+ return "", err
+ }
+
+ var title string
+ var f func(*html.Node)
+ f = func(n *html.Node) {
+ if n.Type == html.ElementNode && n.Data == "title" && n.FirstChild != nil {
+ title = n.FirstChild.Data
+ }
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ f(c)
+ }
+ }
+ f(doc)
+
+ elapsedTime := time.Since(startTime).Round(time.Millisecond)
+ return title + " (" + elapsedTime.String() + ")", nil
+}
+
+
+func crawlURLs(ctx context.Context, urls []string) ([]string, error) {
+
+ var wg sync.WaitGroup
+ wg.Add(len(urls))
+
+
+ titles := make(chan string, len(urls))
+
+ for _, url := range urls {
+
+ go func(url string) {
+ defer wg.Done()
+ title, err := fetchTitle(ctx, url)
+ if err != nil {
+ fmt.Printf("Error fetching %s: %v\n", url, err)
+ titles <- "Error: " + err.Error()
+ return
+ }
+
+ titles <- title
+ }(url)
+ }
+
+
+ wg.Wait()
+ close(titles)
+
+
+ resultTitles := make([]string, 0, len(urls))
+ for title := range titles {
+ resultTitles = append(resultTitles, title)
+ }
+
+ return resultTitles, nil
+}
+
+func main() {
+ urls := []string{
+ "https://www.baidu.com",
+ "https://www.36kr.com",
+ "https://www.sina.com.cn",
+ "https://www.jd.com",
+ "https://www.taobao.com",
+ "https://www.pinduoduo.com",
+ "https://www.tmall.com",
+ "https://www.zhihu.com",
+ "http://www.juejin.cn",
+ "https://www.aliyun.com",
+ }
+
+
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
+
+ titles, err := crawlURLs(ctx, urls)
+ if err != nil {
+ fmt.Println("Error:", err)
+ os.Exit(1)
+ }
+
+ for i, title := range titles {
+ fmt.Printf("%d: %s\n", i+1, title)
+ }
+}
+