go get "google.golang.org/api/youtube/v3"
go get "golang.org/x/oauth2"
youtube api와 OAuth 2.0 클라이언트 인증을 사용하기 위해서 외부 패키지를 다운로드해주세요.
package main
import (
"context"
"fmt"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/option"
"google.golang.org/api/youtube/v3"
"io/ioutil"
"log"
"net/http"
)
func main() {
//Read json file (json 파일 읽어옴)
jsonKey, err := ioutil.ReadFile("client.json")
if err != nil {
log.Fatalf("Failed to read JSON file: %v", err)
}
// Set up the OAuth 2.0 configuration (OAuth 2.0 구성 환경 설정)
config, err := google.ConfigFromJSON(jsonKey, youtube.YoutubeReadonlyScope)
if err != nil {
log.Fatalf("Unable to parse client secret file: %v", err)
}
// Create a new OAuth 2.0 client (새로운 OAuth 2.0 클라이언트를 생성 합니다.)
client := getClient(config)
// Set up the YouTube API client using the authenticated client (인증된 클라이언트를 사용하여 유튜브 API 클라이언트를 설정)
service, err := youtube.NewService(context.Background(), option.WithHTTPClient(client))
if err != nil {
log.Fatalf("Unable to create YouTube service: %v", err)
}
// Retrieve the playlist ID for the private playlist you want to access (접근을 원하는 비공개 재생목록 ID)
playlistID := "자신의 계정에 비공개 재생목록의 ID를 넣어주세요"
// Retrieve the playlist items from the private playlist (비공개 재생목록으로부터 재생목록 아이템들을 불러옵니다.)
playlistItemsCall := service.PlaylistItems.List([]string{"snippet"}).
PlaylistId(playlistID). // 재생목록 ID 설정
MaxResults(50) // Adjust the maximum number of results as per your requirements(가져올 재생목록 item 최대값 설정)
playlistItemsResponse, err := playlistItemsCall.Do() // "youtube.playlistItems.list" 호출 실행.
if err != nil {
log.Fatalf("Unable to retrieve playlist items: %v", err)
}
// Process and display the playlist items //가져온 재생목록 아이템들을 제목과 ID 출력
for _, item := range playlistItemsResponse.Items {
title := item.Snippet.Title
videoID := item.Snippet.ResourceId.VideoId
fmt.Printf("Title: %s, Video ID: %s\n", title, videoID)
}
}
// getClient retrieves a valid OAuth 2.0 client.(유효한 OAuth 2.0 클라이언트를 불러옵니다.)
// 토큰트로 *http.Client를 생성하고 반환
func getClient(config *oauth2.Config) *http.Client {
// Retrieve a token, if it exists, or prompts the user to authenticate.
token := getTokenFromWeb(config)
return config.Client(context.Background(), token)
}
// getTokenFromWeb uses the provided OAuth 2.0 Config to request a Token. (제공된 Auth 2.0 구성을 사용해서 토큰을 요청)
// It returns the retrieved Token.(유효한 토큰을 반환)
func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
fmt.Printf("Go to the following link in your browser, then type the "+
"authorization code: \n%v\n", authURL)
//토큰 입력
var code string
if _, err := fmt.Scan(&code); err != nil {
log.Fatalf("Unable to read authorization code: %v", err)
}
token, err := config.Exchange(context.Background(), code)
if err != nil {
log.Fatalf("Unable to retrieve token from web: %v", err)
}
return token
}
- json 파일과 권한 범위를 가지고 *oauth2.Config 구조체를 구성하고 반환함(토큰을 받기 위한 정보가 있음) jsonKey : 3편에서 다운로드한 json파일 youtube.YoutubeReadonlyScope : 접근 가능한 권한 범위(읽기 전용으로 설정함)
- 인증코드를 얻기 위한 동의 페이지 url을 반환해 준다. (사용자 인증 후 인증코드 반환) "state-token" : csrf 방지를 위한 매개변수 oauth2.AccessTypeOffline : 토큰에 관한 설정에 관한 매개변수 (처음에만 인증하고 재인증 필요 없이 리프레쉬 토큰 재발급 가능)
youtube.NewService(ctx, option.WithAPIKey(*apiKey)) 함수를 사용해서 생성 합니다.
첫 번째 인자는 Context이고, 두 번째 인자는 구글 API 클라이언트에 대한 clientOption 입니다. WithAPIKey를 사용하여 apiKey에 대한 clientOption을 반환해 줍니다.
reqPlaylist := service.PlaylistItems.List([]string{"snippet"}). // Set up snippet option
PlaylistId(*playlistID). //Set up playlistID
MaxResults(50) //Set up Max Result
The expression ~string means the set of all types whose underlying type is string. ~string 표현식은 실제 타입이 string인 모든 타입의 집합을 의미한다.
This includes the type string itself as well as all types declared with definitions such as type MyString string. 이것은 type MyString string와 같은 정의와 함께 선언된 모든 타입들 뿐만 아니라 string타입 자신을 포함합니다.
해석 : type키워드를 사용해서 string을 MyString(Named Type)으로 선언하였다. string과 MyString은 서로 다르다.
하지만 ~string을 사용하면 string자신뿐만 아니라 type MyString string로 선언된 타입까지 사용할 수 있다는 뜻이다.
제네릭으로 예제를 만들어보면,
Integer 인터페이스에 int앞에 tilde(~)를 안 넣어주니 오류가 나온다. MyInt는 Integer를 구현하지 않았다고 나오고 가로 안에 아마 Integer안에 int 앞에 ~를 잃어 버렸다고 한다. Integer 인터페이스 안에 int 앞에 tilde(~) 를 넣어주면 올바르게 작동할 것이다. 이렇게 Integer안에 정의한 자료형들을 underlying type도 허용하고 싶으면 앞에 tilde(~)를 넣어주면 된다.