Go 구문을 계속해서 연습했을 수도 있지만 직접 애플리케이션을 구축하지 않는 한 Go로 애플리케이션을 작성하는 실제 느낌을 깨닫지 못할 것입니다.
이 블로그 게시물에서는 CLI 애플리케이션을 구축할 것입니다. Go, go-grab-xkcd라고 부르겠습니다. 이 애플리케이션은 XKCD에서 만화를 가져오고 명령줄 매개변수를 통해 다양한 작업 옵션을 제공합니다.
우리는 Go 표준 라이브러리를 사용하여 외부 종속성을 사용하지 않고 전체 애플리케이션을 구축할 것입니다.
이 애플리케이션의 아이디어는 다소 어리석게 보일 수 있지만, Google에 인수되는 것을 원하지 않고 Go에서 프로덕션 수준(일종의) 코드 작성을 연습하는 것이 목적입니다.
마지막에 추가 보너스
참고: 이 글에서는 독자가 이미 Go 구문과 용어에 익숙하고 초급과 중급 사이에 있다고 가정합니다.
먼저 애플리케이션을 실행한 다음 진행하겠습니다
$ go-grab-xkcd --help Usage of go-grab-xkcd: -n int Comic number to fetch (default latest) -o string Print output in format: text/json (default "text") -s Save image to current directory -t int Client timeout in seconds (default 30) $ go-grab-xkcd -n 323 Title: Ballmer Peak Comic No: 323 Date: 1-10-2007 Description: Apple uses automated schnapps IVs. Image: https://imgs.xkcd.com/comics/ballmer_peak.png $ go-grab-xkcd -n 323 -o json { "title": "Ballmer Peak", "number": 323, "date": "1-10-2007", "description": "Apple uses automated schnapps IVs.", "image": "https://imgs.xkcd.com/comics/ballmer_peak.png" }
컴퓨터에서 애플리케이션을 다운로드하고 실행하여 다른 옵션을 시도해 볼 수 있습니다.
이 튜토리얼을 마치면 다음 주제에 익숙해질 것입니다:
명령줄 인수 받기
JSON과 Go 구조 간 변환
API 호출 만들기
파일 만들기(인터넷에서 다운로드 및 저장)
문자열 작업
다음은 프로젝트 구조입니다
$ tree go-grab-xkcd go-grab-xkcd ├── client │ └── xkcd.go └── model └── comic.go ├── main.go └── go.mod go.mod - Go Modules file used in Go for package management main.go - Main entrypoint of the application comic.go - Go representation of the data as a struct and operations on it xkcd.go - xkcd client for making HTTP calls to the API, parsing response and saving to disk
1: 프로젝트 초기화
go.mod 파일 만들기 -
$ go mod init
이렇게 하면 패키지 관리에 도움이 됩니다(JS의 package.json 파일 생각).
2: xkcd API
xkcd는 놀랍고 API를 사용하기 위해 등록이나 액세스 키가 필요하지 않습니다. xkcd API "문서"를 열면 두 개의 엔드포인트가 있음을 알 수 있습니다 -
http://xkcd.com/info.0.json - 최신 만화 받기
http://xkcd.com/614/info .0.json - 만화 번호로 지정된 만화 가져오기
다음은 이러한 엔드포인트의 JSON 응답입니다. comic.go의 모델 패키지에 ComicResponse
{ "num": 2311, "month": "5", "day": "25", "year": "2020", "title": "Confidence Interval", "alt": "The worst part is that's the millisigma interval.", "img": "https://imgs.xkcd.com/comics/confidence_interval.png", "safe_title": "Confidence Interval", "link": "", "news": "", "transcript": "" }라는 구조체를 생성하세요
JSON-to-Go 도구를 사용하여 JSON에서 구조체를 자동으로 생성할 수 있습니다.
그런데 다음에서 데이터를 출력하는 데 사용할 다른 구조체를 생성하세요.
type ComicResponse struct { Month string `json:"month"` Num int `json:"num"` Link string `json:"link"` Year string `json:"year"` News string `json:"news"` SafeTitle string `json:"safe_title"` Transcript string `json:"transcript"` Alt string `json:"alt"` Img string `json:"img"` Title string `json:"title"` Day string `json:"day"` }
ComicResponse 구조에 다음 두 가지 메소드를 추가합니다
type Comic struct { Title string `json:"title"` Number int `json:"number"` Date string `json:"date"` Description string `json:"description"` Image string `json:"image"` }
그런 다음 Comic 구조에 다음 두 가지 메소드를 추가합니다
// FormattedDate 函数将格式化日期元素为一个字符串 func (cr ComicResponse) FormattedDate() string { return fmt.Sprintf("%s-%s-%s", cr.Day, cr.Month, cr.Year) } // Comic 函数将从 API 接收到的 ComicResponse 转换为应用程序的输出格式, Comic 结构体 func (cr ComicResponse) Comic() Comic { return Comic{ Title: cr.Title, Number: cr.Num, Date: cr.FormattedDate(), Description: cr.Alt, Image: cr.Img, } }
3: xkcd 클라이언트를 설정하여 요청을 시작하고 응답을 구문 분석한 후 저장합니다. disk
클라이언트 패키지 xkcd.go 파일에서 생성됩니다.
먼저 ComicNumber라는 사용자 정의 유형을 정의하고 데이터 유형은 int입니다.
type ComicNumber int
상수 정의
// PrettyString 函数创建一个漂亮的 Comic 字符串并用于输出 func (c Comic) PrettyString() string { p := fmt.Sprintf( "Title: %s\nComic No: %d\nDate: %s\nDescription: %s\nImage: %s\n", c.Title, c.Number, c.Date, c.Description, c.Image) return p } // JSON 函数将 Comic 结构体转换为 JSON, 我们将使用 JSON 字符串作为输出内容 func (c Comic) JSON() string { cJSON, err := json.Marshal(c) if err != nil { return "" } return string(cJSON) }
XKCDClient 구조를 생성합니다. API에 요청합니다.
const ( // xkcd 的 BaseURL BaseURL string = "https://xkcd.com" // DefaultClientTimeout 是取消请求之前要等待的时间 DefaultClientTimeout time.Duration = 30 * time.Second // 根据 xkcd API, LatestComic 是最新的漫画编号 LatestComic ComicNumber = 0 )
Read 명령줄 매개변수
Instantiate XKCDClient
XKCDClient를 사용하여 API에서 데이터를 가져옵니다
Output
Read 명령줄 매개변수
// XKCDClient 是 XKCD 的客户端结构体 type XKCDClient struct { client *http.Client baseURL string } // NewXKCDClient 创建一个新的 XKCDClient func NewXKCDClient() *XKCDClient { return &XKCDClient{ client: &http.Client{ Timeout: DefaultClientTimeout, }, baseURL: BaseURL, } }
flag.Parse에 다음 4가지 메서드를 추가합니다. ()
XKCDClient 인스턴스화
// SetTimeout 重写了默认的 ClientTimeout func (hc *XKCDClient) SetTimeout(d time.Duration) { hc.client.Timeout = d }
API에서 XKCDClient를 사용하여 데이터 가져오기
// Fetch 根据提供的漫画编号检索漫画 func (hc *XKCDClient) Fetch(n ComicNumber, save bool) (model.Comic, error) { resp, err := hc.client.Get(hc.buildURL(n)) if err != nil { return model.Comic{}, err } defer resp.Body.Close() var comicResp model.ComicResponse if err := json.NewDecoder(resp.Body).Decode(&comicResp); err != nil { return model.Comic{}, err } if save { if err := hc.SaveToDisk(comicResp.Img, "."); err != nil { fmt.Println("Failed to save image!") } } return comicResp.Comic(), nil }
output
// SaveToDisk 下载并保存漫画到本地磁盘 func (hc *XKCDClient) SaveToDisk(url, savePath string) error { resp, err := http.Get(url) if err != nil { return err } defer resp.Body.Close() absSavePath, _ := filepath.Abs(savePath) filePath := fmt.Sprintf("%s/%s", absSavePath, path.Base(url)) file, err := os.Create(filePath) if err != nil { return err } defer file.Close() _, err = io.Copy(file, resp.Body) if err != nil { return err } return nil }
프로그램은 다음과 같이 실행됩니다
func (hc *XKCDClient) buildURL(n ComicNumber) string { var finalURL string if n == LatestComic { finalURL = fmt.Sprintf("%s/info.0.json", hc.baseURL) } else { finalURL = fmt.Sprintf("%s/%d/info.0.json", hc.baseURL, n) } return finalURL }
또는 노트북에서 바이너리 실행 파일로 빌드하여 실행하세요
comicNo := flag.Int( "n", int(client.LatestComic), "Comic number to fetch (default latest)", ) clientTimeout := flag.Int64( "t", int64(client.DefaultClientTimeout.Seconds()), "Client timeout in seconds", ) saveImage := flag.Bool( "s", false, "Save image to current directory", ) outputType := flag.String( "o", "text", "Print output in format: text/json", )
전체 소스 코드는 다음과 같습니다. 이 Github 저장소에서 찾을 수 있습니다 - go-grab-xkcd
추가 보너스이 간단한 쉘 마법 도구를 사용하여 여러 만화를 순서대로 다운로드할 수 있습니다
xkcdClient := client.NewXKCDClient() xkcdClient.SetTimeout(time.Duration(*clientTimeout) * time.Second)
위의 쉘 코드는 단순히 go-grab-xkcd 명령을 호출합니다 for 루프에서는 xkcd가 정수 시퀀스를 사용하므로 i 값을 만화 번호/ID로 만화 번호로 바꿉니다.
권장 튜토리얼: "
PHP" "
Go Tutorial"
위 내용은 Go를 사용하여 CLI 프로그램 빌드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!