정상적으로 작동하는 URL인지 체크해주는 미니 프로젝트 입니다.
main.go
package main
import (
"errors"
"fmt"
"net/http"
)
var errRequestFailed = errors.New("Request failed")
func main() {
urls := []string{
"https://www.airbnb.com/",
"https://www.google.com/",
"https://www.amazon.com/",
"https://www.reddit.com/",
"https://www.google.com/",
}
for _, url := range urls {
hitURL(url)
}
}
func hitURL(url string) error {
fmt.Println("Checking:", url)
resp, err := http.Get(url)
if err != nil || resp.StatusCode >= 400 { // url이 없거나 StatusCode가 400 이상이라면
return errRequestFailed
}
return nil
}
// Checking: https://www.airbnb.com/
// Checking: https://www.google.com/
// Checking: https://www.amazon.com/
// Checking: https://www.reddit.com/
// Checking: https://www.google.com/
Status Code
- 1xx(정보) : 요청을 받았으며 프로세스를 계속 진행
- 2xx(성공) : 요청을 성공적으로 받았으며 인식, 수용
- 3xx(리다이렉션) : 요청 완료를 위해 추가 작업 조치 필요
- 4xx(클라이언트 오류) : 요청의 문법이 잘못되었거나 요청을 처리할 수 없음
- 5xx(서버 오류) : 서버가 명백히 유효한 요청에 대한 충족 실패
위의 urlChecker는 url을 하나씩 순차적으로 체크하기 때문에 느립니다.
Goroutines
은 다른 함수와 동시에 실행시키는 함수 입니다.
Goroutines
을 사용하려면 함수 앞에 go
를 붙여주기만하면 됩니다.
func main() {
go sexyCount("jisoo")
sexycount("lee")
}
func sexyCount(person string) {
for i:=0;i<2;i++ {
fmt.Println(person, "is sexy", i)
time.Sleep(time.Second) // time은 go 패키지
}
}
// lee is sexy 0
// jisoo is sexy 0
// jisoo is sexy 1
// lee is sexy 1
// lee is sexy 2
// jisoo is sexy 2
함수 앞에 go
를 붙이면 jisoo is sexy와 lee is sexy를 동시에 출력됩니다. sexyCount
두 함수가 동시에 실행되는 것입니다.
출력 결과를 보면 두 함수가 동시에 출력됩니다.
func main() {
go sexyCount("jisoo")
go sexycount("lee")
}
하지만 두 함수 모두에 go
를 붙히게되면 main
함수가 바로 종료되기 때문에 두 함수 모두 실행되지 않습니다.
Gorountines는 main
함수가 실행되고 있을 경우에만 유효합니다.
channel은 goroutine과 goroutine, 혹은 메인함수 사이에 정보를 전달하기 위한 방법입니다.
func main() {
// Channels
c := make(chan string) // channel 생성
people := [2]string{"jisoo", "lee"}
for _, person := range people {
go isSexy(person, c)
}
for i := 0; i < len(people); i++ {
fmt.Println(<-c) // channel로부터 메세지를 가져옴
}
}
func isSexy(person string, c chan string) {
time.Sleep(time.Second * 10)
c <- person + " is sexy" // channel로 메세지를 보냄
}
// jisoo is sexy
// lee is sexy
c <- 메세지
입니다.type requestResult struct {
url string
status string
}
var errRequestFailed = errors.New("Request failed")
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) { // chan<- : SEND only
resp, err := http.Get(url)
status := "OK"
if err != nil || resp.StatusCode >= 400 {
status = "FAILED"
}
c <- requestResult{url: url, status: status}
}
// https://www.amazon.com/ OK
// https://www.reddit.com/ FAILED
// https://www.instagram.com/ OK
// https://www.google.com/ OK
// https://www.airbnb.com/ OK
// https://soundcloud.com/ OK
// https://www.facebook.com/ OK
// https://academy.nomadcoders.co/ OK
출력 시간은 가장 오래 걸리는 하나의 url을 체크하는 시간과 같습니다.
처음의 hitURL처럼 하나의 url체크를 마치고 다음으로 넘어가는 것이아니라 url을 동시에 체크하기 때문에 출력 속도가 매우 빠릅니다.