Go in Action - 2(feed)

김민진·2022년 4월 10일
0

go

목록 보기
3/6
package search

import (
	"encoding/json"
	"os"
)

const dataFile = "data/data.json"

search.go 코드에서 사용한 RetrieveFeeds 함수의 구성 내용이다.

"encoding/json"

json 패키지의 JSON 데이터를 인코딩/디코딩 하는 기능을 제공하며

"os"

os 패키지는 파일을 읽는 등의 운영체제 기능을 활용할 수 있는 패키지다.

const dataFile = "data/data.json"

dataFile 이라는 이름의 상수를 선언하고 이 상수에 디스크상의 데이터 파일을 가리키는 상대 경로를 표현하는 문자열을 대입했다.

Go 컴파일러는 대입 연산자 오른쪽의 값을 바탕으로 변수의 타입을 유추할 수 있기 때문에 상수를 선언할대 타입을 명시할 필요가 없다. 또한 상수 이름이 소문자이므로 이 상수는 외부로 노출되지 않는 비공개 상수가 되며 따라서 search 패키지 외부의 코드가 이 상수에 직접 접근할 수 없다.

type Feed struct {
	Name string `json:"site"`
	URI  string `json:"link"`
	Type string `json:"type"`
}

Feed 라는 이름의 구조체 타입을 선언한다. 이 구조체는 패키지 외부로 노출되는 타입이다.

func RetrieveFeeds() ([]*Feed, error) {
	// 파일을 연다.
	file, err := os.Open(dataFile)
	if err != nil {
		return nil, err
	}

	// defer 함수를 이용해 이 함수가 리턴될 때
	// 앞서 열어둔 파일이 닫히도록 한다.
	defer file.Close()

	// 파일을 읽어 Feed 구조체의 포인터의
	// 슬라이스로 변환한다.
	var feeds []*Feed
	err = json.NewDecoder(file).Decode(&feeds)

	// 호출 함수가 오류를 처리할 수 있으므로 오류 처리는 하지 않는다.
	return feeds, err
}
func RetrieveFeeds() ([]*Feed, error) {

함수 선언부를 보면 이 함수는 매개변수를 정의하지 않으며 두 개의 값을 리턴한다.

첫 번째 리턴 값은 Feed 타입 값들의 슬라이스에 대한 포인터 이다.

두 번째 리턴 값은 함수 호출이 성공하지 못한 경우에 이를 보고하기 위한 error값이다.

앞으로 계속해서 보겠지만 이와 같이 에러 값을 리턴하는 것은 코드 예제뿐만 아니라 표준 라이브러리 전반에 걸쳐 적용된 보편화된 규칙이다.

	file, err := os.Open(dataFile)

os 패키지를 이용해 데이터 파일을 여는 코드를 볼 수 있다.
Open 메서드를 호출할 때 데이터 파일의 상대 경로를 지정하면 두 개의 리턴 값을 전달받을 수 있다.
첫 번째 리턴 값은 File 타입 구조체에 대한 포인터 이며 두 번째 리턴 값은 Open 메서드 호출이 성공했는지 판단하기 위한 에러 값이다.

defer file.Close()

defer 키워드는 함수가 리턴된 직후에 실행될 작업을 예약하기 위한 키워드다.

필요한 작업을 수행한 후 파일을 닫는 것은 전적으로 개발자의 몫이다.

이 경우 defer 키워드를 이용하면 close 메서드 호출을 예약하여 이 메서드가 반드시 호출되도록 보장할 수 있다.

이렇게 예약된 작업은 심지어 함수가 패닉 상태에 빠져 예상치 못하게 종료되더라도 반드시 실행된다.

defer 키워드를 이용하면 파일을 여는 코드 주변에 파일을 닫기 위한 코드를 작성할 수 있기 때문에 가독성이 향상되는 것은 물론 개발자의 실수로 인한 버그도 줄일 수 있다.

var feeds []*Feed
	err = json.NewDecoder(file).Decode(&feeds)

	// 호출 함수가 오류를 처리할 수 있으므로 오류 처리는 하지 않는다.
	return feeds, err

feeds 라는 이름으로 빈 슬라이스 변수가 생성된다.

이 변수는 Feed 타입 값들에 대한 포인터 변수다.

Decode 메서드는 어떤 타입이든 받아들일 수 있도록 설계되어 있다.

func (dec *Decoder) Decode(v interface{}) error

Decode 메서드의 매개변수는 interface{} 타입의 값을 전달받는다. 이 값은 Go 에서는 특별하게 취급하는 타입이며 reflect 패키지를 이용한 리플렉션 지원이 가능한 타입이다.

profile
dart,c#,java 개발자! 잡다하게 해서 문제될게 없다!

0개의 댓글