본문 바로가기

SW LAB/Go Lang

[Google Go 언어] 미니 프로젝트 : URL Checker

Step 1

  • 여러 개의 URL의 상태를 순차적으로 체크해보자
  • `main.go`
package main

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

var errRequestFailed = errors.New("Request failed")

func main() {
	var results = make(map[string]string)
	urls := []string{
		"https://www.airbnb.com/",
		"https://www.google.com/",
		"https://www.amazon.com/",
		"https://www.reddit.com/",
		"https://www.google.com/",
		"https://soundcloud.com/",
		"https://www.facebook.com/",
		"https://www.instagram.com/",
		"https://academy.nomadcoders.co/",
	}
	for _, url := range urls {
		result := "OK"
		err := hitURL(url)
		if err != nil {
			result = "FAILED"
		}
		results[url] = result
	}
	for url, result := range results {
		fmt.Println(url, result)
	}
}

func hitURL(url string) error {
	fmt.Println("Checking:", url)
	resp, err := http.Get(url)
	if err != nil || resp.StatusCode >= 400 {
		return errRequestFailed
	}
	return nil
}

Step 2

  • Goroutines를 이용하여 동시에 체크해봅니다.
  • Channel를 이용하여 함수나 goroutine 간에 통신을 해봅니다.
  • `main.go` 다음과 같이 할 경우 프로그램이 즉시 종료됩니다. main() 함수와 channel 를 구성해야 합니다.
package main

import (
	"fmt"
	"time"
)

func main() {
	go sexyCount("nico")
	go sexyCount("flynn")
}

func sexyCount(person string) {
	for i := 0; i < 10; i++ {
		fmt.Println(person, "is sexy", i)
		time.Sleep(time.Second)
	}
}
  • `main.go` 채널을 정의하고 goroutine 에서 channel 로 메시지를 보내야 합니다. 그리고 main 에서는 channel 으로부터 메시지를 수신 받기 전까지 대기합니다.
package main

import (
	"fmt"
	"time"
)

func main() {
	c := make(chan string)
	people := [4]string{"kjham", "aejin", "chaeeun", "charin"}
	for _, person := range people {
		go isSexy(person, c)
	}
	fmt.Println("Waiting for messages")
	for i := 0; i < len(people); i++ {
		fmt.Println("Received this message:", <-c)
	}
}

func isSexy(person string, c chan string) {
	time.Sleep(time.Second * 5)
	c <- person + " is sexy"
}

Step 3

  • goroutine, channel 을 이용하여 url checker 를 구현해봅니다.
  • `main.go` channel로 사용할 requestResult 를 선언합니다. 그리고 결과를 results에 담아서 최종적으로 출력합니다.
import (
	"fmt"
	"net/http"
)

type requestResult struct {
	url    string
	status string
}

func main() {
	results := make(map[string]string)
	c := make(chan requestResult)
	urls := []string{
		"https://www.airbnb.com/",
		"https://www.google.com/",
		"https://www.amazon.com/",
		"https://www.reddit.com/",
		"https://www.google.com/",
		"https://soundcloud.com/",
		"https://www.facebook.com/",
		"https://www.instagram.com/",
		"https://academy.nomadcoders.co/",
	}
	for _, url := range urls {
		go hitURL(url, c)
	}
	for i := 0; i < len(urls); i++ {
		result := <-c
		results[result.url] = result.status
	}

	for url, status := range results {
		fmt.Println(url, status)
	}
}

func hitURL(url string, c chan<- requestResult) {
	resp, err := http.Get(url)
	status := "OK"
	if err != nil || resp.StatusCode >= 400 {
		status = "FAILED"
	}
	c <- requestResult{url: url, status: status}
}