[The Go Programming Language] 1장 튜토리얼 - 1.5, 1.6 URL 반입(Fetching)
안녕하세요. 개발자 모도리입니다.
The Go Programming Language 라는 책으로 Go를 공부하고 있으며, 해당 책의 내용을 요약 정리해서 올리려고 합니다. 저는 번역본을 구매해서 공부하고 있습니다.
지난 게시물
- [Go] Mac에서 Atom으로 Go 개발 환경 구축하기
- [The Go Programming Language] 1장 튜토리얼 - 1.1 Hello, World
- [The Go Programming Language] 1장 튜토리얼 - 1.2 커맨드라인 인수
- [The Go Programming Language] 1장 튜토리얼 - 1.3 중복 줄 찾기
- [The Go Programming Language] 1장 튜토리얼 - 1.4 애니메이션 GIF
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 채널을 통해 보낸 결과를 출력합니다.
@modolee, I gave you a vote!
If you follow me, I will also follow you in return!
이어보기
[The Go Programming Language] 1장 튜토리얼 - 1.7 웹 서버