[The Go Programming Language] 1장 튜토리얼 - 1.5, 1.6 URL 반입(Fetching)

in #kr-dev6 years ago

modolee_logo
안녕하세요. 개발자 모도리입니다.
The Go Programming Language 라는 책으로 Go를 공부하고 있으며, 해당 책의 내용을 요약 정리해서 올리려고 합니다. 저는 번역본을 구매해서 공부하고 있습니다.

지난 게시물


1장 튜토리얼

1.5 URL 반입(Fetching)

  • 지정한 URL에서 내용을 가져오고 이를 원본 그대로 출력하는 프로그램
//Fetch는 url에서 찾은 내용을 출력합니다.
package main

import (
  "fmt"
  "io/ioutil"
  "net/http"
  "os"
)

func main() {
  for _, url := range os.Args[1:] {
    resp, err := http.Get(url)
    if err != nil {
      fmt.Fprintf(os.Stderr, "fetch: %v\n", err)
      os.Exit(1)
    }
    b, err := ioutil.ReadAll(resp.Body)
    resp.Body.Close()
    if err != nil {
      fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err)
      os.Exit(1)
    }
    fmt.Printf("%s", b)
  }
}

예제코드 [ch1/fetch.go]

실행결과
$ go run ch1/fetch.go http://gopl.io > gopl.html
gopl.html 파일을 확인하면 http://gopl.io의 소스코드가 있는 것을 확인할 수 있습니다.

  • net/http 패키지
    • http.Get 함수 : HTTP 요청을 생성하고 오류가 없으면 결과를 응답 구조체 resp로 반환합니다.
    • resp의 Body 필드 : 읽을 수 있는 스트림 형태의 서버 응답이 포함되어 있습니다.
  • io/ioutil 패키지
    • ioutil.ReadAll 함수 : 전체 응답을 읽습니다.
    • 결과는 b에 저장됩니다.

그 외 코드 설명

  • Body 스트림은 리소스의 누출을 막기 위해 닫습니다.
  • Printf는 표준 출력에 응답을 기록합니다.

1.6 URL 동시 반입(Fetching)

  • 고루틴(Goroutine)과 채널(Channel)을 사용합니다.
  • 동시에 여러 URL의 내용을 가져와 결과는 버리고, 대신 각 결과의 크기와 가져오는데 걸리는 시간을 보고합니다.
// Fetchall은 URL을 병렬로 반입하고 시간과 크기를 보고합니다.
package main

import (
  "fmt"
  "io"
  "io/ioutil"
  "net/http"
  "os"
  "time"
)

func main() {
  start := time.Now()
  ch := make(chan string)
  for _, url := range os.Args[1:] {
    go fetch(url, ch) // 고루틴 시작
  }
  for range os.Args[1:] {
    fmt.Println(<-ch) // ch 채널에서 수신
  }
  fmt.Printf("%.2fs elapsed\n", time.Since(start).Seconds())
}

func fetch(url string, ch chan<- string) {
  start := time.Now()
  resp, err := http.Get(url)
  if err != nil {
    ch <- fmt.Sprint(err) // ch 채널로 송신
    return
  }
  nbytes, err := io.Copy(ioutil.Discard, resp.Body)
  resp.Body.Close() // 리소스 누출 방지
  if err != nil {
    ch <- fmt.Sprintf("while reading %s: %v", url, err)
    return
  }
  secs := time.Since(start).Seconds()
  ch <- fmt.Sprintf("%.2fs %7d %s", secs, nbytes, url)
}

예제코드 [ch1/fetchall.go]

실행결과
$ go build ch1/fetchall.go
$ ./fetchall https://golang.org http://gopl.io https://godoc.org
0.68s 6815 https://godoc.org
0.84s 4154 http://gopl.io
4.84s 8759 https://golang.org
4.84s elapsed

  • 고루틴, 채널
    • 고루틴 : 함수의 동시 실행
    • 채널 : 한 고루틴에서 지정된 타입의 값을 다른 고루틴으로 전달하는 통신 방식
    • make로 문자열의 채널을 만듭니다.
    • 첫번째 루프에서는 go 문을 통해서 fetch 함수를 비동기 호출합니다.
    • fetch 함수에서는 각 결과가 도착하는 대로 ch 채널에 요약된 결과를 보냅니다.
    • 두번째 루프에서는 fetch에서 ch 채널을 통해 보낸 결과를 출력합니다.
Sort:  

@modolee, I gave you a vote!
If you follow me, I will also follow you in return!

Coin Marketplace

STEEM 0.27
TRX 0.11
JST 0.030
BTC 69245.03
ETH 3778.28
USDT 1.00
SBD 3.51