Reducing boilerplate with go generate 를 번역한 글입니다 Go는 대단한 언어입니다. 단순하고, 파워풀하며, 훌륭한 도구들을 가지고 있고, 우리 중 많은 이들은 매일 사용하는 것을 즐깁니다. 하지만 강한 타입의 언어들에서 일상적으로 발생하게 되는, 이것저것을 연결하기 위해서 필수로 사용해야 하는 boilerplate를 쓰게 됩니다. 이 포스트에서 다음의 세가지 포인트를 다룰 것입니다: 코드 생성(code generation)을 사용하여 boilerplate를 줄이도록 도와주는 Go 도구들을 만들 수 있어야 하는 이유는 무엇입니까. Go 코드 생성을 위한 블록 구성 요소는 무엇입니까.
Structuring Applications in Go을 번역한 글입니다. 개요 Go를 배울 때 가장 어려웠던 부분은 애플리케이션을 어떻게 설계하는가였다. Go 이전에, 나는 Rails 애플리케이션을 만들었었는데 Rails는 애플리케이션을 특정한 방식으로 설계하도록 한다. “설정보다는 컨벤션”이라는게 그들의 모토였다. 그러나 Go는 그 어떤 프로젝트 구조나 애플리케이션 설계방식을 규정짓고 있지 않으며 Go의 컨벤션은 대개 제각각이다. 나는 Go 애플리케이션의 아키텍쳐를 구성하면서 발견한 정말 많은 도움이 되었던 4가지 패턴을 여러분에게 알려주려고한다. 이들은 공식적인 규칙은 아니며 누군가는 다른 의견을 가질 수 있다고 생각한다.
객체지향 프로그래밍 Go는 클래스(Class)가 없다!! Struct가 Class의 역할을 수행 할 수 있기는 하지만 메서드도 구조체로부터 분리되는 구성을 가지고 있다. 단일 상속도 없고 당연히 다중 상속도 없다. 왠지 객체지향스럽지 않은 언어로 보일 수 있겠지만 충분히 객체지향적이다. 그냥 좀 다른 방법으로 객체를 지향하고 있을 따름이다. struct가 클래스를 대신한다. 다른 OOP에서의 클래스와는 달리 non-virtual(real) 메서드로만 구성된다. receiver로 구조체와 함수를 연결 해서 메서드를 구현한다. 네임스페이스(namespacing)는 exports로 대신한다. 인터페이스(interfaces)로 다형성을 구현할 수 있다. 다른 OOP에서는 필드 없이, virtual 메서드로만 구성된 클래스 형태로 구현된다.
이 포스트는 Golang 내부 시리즈의 연속이다. Go 런타임을 자세히 이해하는데 열쇠와 같은 부트스트랩 과정을 살펴볼 것이다. 이번에는 시작하는 순서의 두번째 부분을 섭렵해서 어떻게 인수들이 초기화되고, 어떤 함수들이 호출되는지 등을 배우겠다. 시작하는 순서 지난 번에 얘기하다가 만 runtime.rt0_go 함수를 다시 다루어야 겠다. 아직 이 함수에서 살펴보지 않은 부분이 여전히 있다. 01 CLD // convention is D is always left cleared 02 CALL runtime·check(SB) 03 04 MOVL 16(SP), AX // copy argc 05 MOVL AX, 0(SP) 06 MOVQ 24(SP), AX // copy argv 07 MOVQ AX, 8(SP) 08 CALL runtime·args(SB) 09 CALL runtime·osinit(SB) 10 CALL runtime·schedinit(SB) 첫번째 명령 (CLD)는 FLAGS 레지스터의 direction 프래그를 지운다.
부트스트래핑 과정은 Go의 런타임이 어떻게 작동하는지를 이해하는데 열쇠와 같은 구실을 한다. Go와 함께 앞으로 나아가고자 한다면 반드시 배워야한다. 그래서 Golang의 내부 시리즈의 다섯번째는 Go의 런타임, 특히 Go의 부트스트래핑 과정에 바치겠다. 이번에 독자가 배울 항목들은: Go 부트스트래핑 가변 스택 구현 TLS 내부 구현 이 포스트에 어셈블러 코드가 많이 포함되어 있는 점을 주목하라. 진행하기 위해 적어도 어셈블러의 기본 지식은 필요할 것이다. (속성 Go 어셈블러 가이드가 여기 있다.) 이제 시작해 보자! 프로그램 시작점 찾기 우선, Go 프로그램이 시작된 후 즉시 실행되는 함수가 무엇인지 찾아보자.
오늘은, Func 구조에 대해 좀 더 자세히 들여다 보고 어떻게 가비지 컬렉션이 작동하는지 몇가지 자세한 내용을 논하겠다. 이 포스트는 Golang의 내부, 3부: 링커, 오브젝트 파일, 그리고 재배치의 연속이어서, 독자가 아직 읽지 않았다면 이 포스트를 소화하기 전에 읽기를 적극 권장한다. 함수 메타데이터의 구조 재배치에 대한 주요한 아이디어는 3부를 통해 분명해 졌을 것이다. 이제 main 메서드의 Func 구조를 살펴보자: 01 Func: &goobj.Func{ 02 Args: 0, 03 Frame: 8, 04 Leaf: false, 05 NoSplit: false, 06 Var: { 07 }, 08 PCSP: goobj.Data{Offset:255, Size:7}, 09 PCFile: goobj.Data{Offset:263, Size:3}, 10 PCLine: goobj.Data{Offset:267, Size:7}, 11 PCData: { 12 {Offset:276, Size:5}, 13 }, 14 FuncData: { 15 { 16 Sym: goobj.SymID{Name:"gclocals·3280bececceccd33cb74587feedb1f9f", Version:0}, 17 Offset: 0, 18 }, 19 { 20 Sym: goobj.SymID{Name:"gclocals·3280bececceccd33cb74587feedb1f9f", Version:0}, 21 Offset: 0, 22 }, 23 }, 24 File: {"/home/adminone/temp/test.go"}, 25 }, 이 구조체는 Go언어의 런타임이 사용하는, 컴파일러가 오브젝트 파일에 방출한 함수 메타데이터로 생각해 볼 수 있다.
오늘은 Go 링커와 오브젝트 파일, 그리고 재배치(relocations)에 대해 얘기해 보자. 이런 것들이 독자들과 무슨 상관이 있을까? 만약 독자가 어떤 대형 프로젝트의 내부에 대해 배우고자 한다면, 첫번째 할 일이 그 것을 콤포넌트나 모듈로 자를 필요가 있다. 둘째로 이 모듈들이 서로에게 어떤 인터페이스를 제공하는지 이해할 필요가 있다. Go 언어 프로젝트의 경우, 이런 상위 모듈들이 컴파일러, 링커, 그리고 런타임이다. 컴파일러가 제공하고 링커가 사용하는 것이 오프젝트 파일인데, 오늘은 그 것으로 조사를 시작해 보자. Go 오브젝트 파일 생성하기 실용적인 실험을 하나 해 보자-아주 간단한 프로그램을 하나 만들고, 컴파일하고, 어떤 오브젝트 파일이 만들어 지는지 관찰하자.
독자는 인터페이스 레퍼런스를 통해 변수를 사용할 경우 Go 런타임내에서 어떤 일이 있는지 정확하게 알고 있는가? 이 질문에 쉽게 답할 수 없는 이유는 어떤 인터페이스를 구현하는 타입의 경우 그 인터페이스를 가리키는 어떤 레퍼런스도 갖고 있지 않기 때문이다. 하지만 여전히 시도는 해 볼 수 있는데 이전 블로그 포스트에서 논했던 Go 컴파일러의 지식을 이용하는 것이다. 그러면, Go 컴파일러속으로 잠수해 들어가자: 간단한 Go 프로그램을 제작하고 Go 타입캐스팅(typecasting)이 내부적으로 어떻게 동작하는 지 살펴보겠다. 이 것을 예로 들면서, 어떻게 노드 트리가 생성되고 사용되는지 설명하겠다.
이 블로그 시리즈는 기본적인 Go 언어특성에 이미 익숙하며 좀 더 심도있게 내부구조를 알고자 하는 독자들을 위해 쓰여졌다. 이 포스트는 Go언어의 소스코드의 구조와 Go 컴파일러의 내부를 어느 정도 상세히 살펴보겠다. 이 글을 읽고 난 후, 독자는 다음과 같은 질문에 답을 얻을 것이다. Go의 소스코드는 어떤 구조를 가지고 있는가? Go의 컴파일러는 어떻게 동작하는가? Go의 노드 트리(node treee)의 기본 구조는 무엇인가? 시작하며 새로운 프로그래밍 언어를 배우기 시작할 때, 보통은 “hello-world”와 같은 튜토리얼이나, 초보자 가이드, 그리고 언어의 주요한 컨셉트, 문법, 심지어 표준 라이브러리에 대한 상세한 정보들 많이 접하게 된다.
Go 언어의 최신 컴파일러에 대한 내용 GopherCon 2016: Rob Pike - The Design of the Go Assembler Video Slides GopherCon 2014 Go from C to Go by Russ Cox Video Slides GopherFest 2015: Rob Pike on the move from C to Go in the toolchain Video Slides Go의 어셈블러 A Quick Guide to Go’s Assembler