Golang 다형성 메모

Dev 2021. 3. 14. 17:25

컴파일되는 JavaScript

개인적으로는 golang(고랭, 고언어)을 컴파일되는 JavaScript라고 생각한다.
golang에는 드러나지 않는 곳에서 많은 것을 처리하는 golang 런타임(JavaScript 인터프리터에서 파생된 무엇?)이 숨어있다. 그리고 golang 컴파일러는 golang 런타임을 뜯어서 큰 힘 들이지 않고 쉽게 만든 것 같다 (이건 칭찬이다). golang은 아름다움보다는 실용성을 추구한 언어다. 그게 golang의 매력이다.

 

같은듯 다른 '객체 (Object)'

c++ 같은 OOP 언어에서 객체는 변수와 메소드의 덩어리다. 그리고 type이다. c++로 객체지향 프로그래밍을 한다는 것은 달리 말하면 type을 정의하는 일이다.
반면, JavaScript에서 객체는 key-value 테이블이다. 그리고 instance다. JS Object를 딱히 type이라고 부르기 어려운 것이 JavaScript에서는 JS Object 아닌 것이 없기 때문이다. int도 JS Object이고, string도 JS Object이고, 심지어 function도 JS Object다.

 

다형성을 책임지는 interface 타입

golang은 type을 철저하게 체크한다. 하지만 JavaScript보다 조금 더 엄격한 정도다.
golang 코드의 interface 타입은 컴파일 시점에 결정되지 않는다. 실행 시점에 golang 런타임이 interface 타입을 체크한다 (즉, interface 타입 변수가 interface로서 갖춰야할 method 들을 구비하고 있는지 체크한다).

 

"Essential Go" 책의 설명을 참조하자.
https://essential-go.programming-books.io/reflection-c7fea6b176b74c54ab35f2d8fdd56f13

 

Reflection

Reflection

essential-go.programming-books.io

Go는 정적 타입 랭귀지다. 대부분의 경우 변수의 타입은 컴파일 시점에 알 수 있다. 하지만 interface 타입은 예외다. interface 타입 뒤에 있는 값이 실제 무슨 타입인지 컴파일 시점에는 알 수 없다.

 

요약하면 다음과 같다.

  • interface 타입으로 어떤 method가 필요한지 규격을 정의할 수 있다.
  • struct 타입으로 필요한 method를 구현할 수 있다.
  • 어떤 struct가 어떤 interface 규격을 만족시키는지 언어적으로는 명시하지 않는다 (명시할 수 없다). golang 런타임이 실행 시점에 체크한다.

 

샘플코드 - interface 타입을 이용한 다형성 구현

상이한 타입의 변수들을 단일한 interface로 일관성있게 다루는 것이 다형성의 매력이다.

package main

import (  
  "fmt"  
)

type writer interface {  
  write()  
}

type koreanWriter struct{}

func (k koreanWriter) write() {  
  fmt.Println("안녕하세요")  
}

type englishWriter struct{}

func (e englishWriter) write() {  
  fmt.Println("Hello")  
}

func main() {  
  kw := koreanWriter{}
  ew := englishWriter{}
  wa := []writer{kw, ew} 
  
  for _, iw := range wa {  
    iw.write()  
    //  
    // 상이한 타입의 변수들을 단일한 interface로  
    // 일관성있게 다루는 것이 다형성의 매력 
    //  
  }  
}

Posted by ingeeC
,

GOPATH와 module 관련 소식

Golang 의존성 관리 규칙이 바뀔 참이라고 한다. 2019년 8월 golang 1.13과 함께 공식 릴리즈 된다고 하니 그때까지는 지켜보는게 좋겠다.

An intro to dep: How to manage your Golang project dependencies

https://medium.freecodecamp.org/an-intro-to-dep-how-to-manage-your-golang-project-dependencies-7b07d84e7ba5
2018-11-26
  • Golang 툴체인에 의존성 관리 기능이 내장됨
  • dep 도구는 Golang의 공식 의존성 관리 도구가 아님

Go Modules in 2019

https://blog.golang.org/modules2019
2018-12-19
  • 패키지 의존성 관리에 관한 커뮤니티 차원의 토론이 있었음. 향후 패키지 의존성 관리를 위해 module 개념을 도입할 것임. module 개념이 GOPATH 사용을 대치할 것임.
  • module 지원 계획
    • go 1.11 (2018년 8월 출시) ~ module 개념 시험 도입 (go.mod 파일 이용)
    • go 1.12 (2019년 2월 출시) ~ module 개념 지원 강화 (go run, go get 명령과 연계)
    • go 1.13 (2019년 8월 예정) ~ module 개념 디폴트 적용

결론

지금은 GOPATH 환경변수만 쓰고, module 개념은 8월가서 공부하기로 함.


Posted by ingeeC
,

VIM-GO, Golang 개발환경 꾸미기


회사 업무 때문에 Golang을 쓰고 있다. 코딩 스타일과 디렉토리 구조를 강제하는 점이 불만이지만, 그에 대한 반대급부로 편리함을 제공해준다. Golang은 개성이 중요한 예술가적 마인드의 개발자를 위한 도구가 아니라 문제해결이 중요한 실용가적 마인드의 개발자를 위한 도구인 것 같다.

Golang이 강제하는 코딩 스타일과 디렉토리 구조를 받아들인다면, 주요 OS마다 제공되는 표준 툴의 편리함과 일관됨을 누릴 수 있다. Golang을 설치하고 vim-go를 설치하면 다른 번잡한 툴이 필요 없다.

Golang 툴 설치

https://golang.org/doc/install 페이지가 안내하는 대로 따라하면 어렵지 않게 설치할 수 있다. GOROOT 환경변수와 GOPATH 환경변수 설정이 중요하다. GOROOT는 Golang 툴이 설치된 root 디렉토리 (예를 들어 /usr/local/go)이고, GOPATH는 Golang 프로젝트 관리를 위해 사용할 home 디렉토리 (예를 들어 /home/some-usr/go)이다. GOPATH 디렉토리 아래에는 툴에 의해 bin, pkg, src 디렉토리가 강제로 생성되고 관리된다. 개발자는 $GOPATH/src/ 디렉토리 아래에 프로젝트 디렉토리를 만들어야 한다 (안 내켜도 받아들이는게 편하다).

Vim-go 설치

  1. Vundle (VIM 플러그인 매니저) 설치
    .vimrc 설정파일을 GitHub에 올렸다. 해당 파일에 Vundle 플러그인 매니저의 설치방법도 메모해뒀다.
    https://gist.github.com/ingee/0554f2a8ae8c018d0f8b0c0c2c322767
  2. vim-go (Golang VIM 플러그인) 설치
    VIM 에디터에는 Vundle 말고도 다양한 플러그인 매니저가 존재한다. 어느 플러그인 매니저를 사용하든 상관 없다. VimAwesome 페이지(https://vimawesome.com/)를 방문하면 수많은 VIM 플러그인들의 목록과 설치방법을 확인할 수 있다. Golang 프로젝트 개발을 위해서는 vim-go 플러그인을 설치해야 한다. 바로 위 .vimrc 파일에는 Vundle 플러그인 매니저를 이용해서 vim-go 를 활용하는 설정이 이미 존재한다. .vimrc 를 수정한 다음, vim 을 실행시키고 커맨드 모드에서 :PluginInstall 을 실행시키면 vim-go 가 설치된다. vim-go 가 설치된 상태에서 :GoInstallBinaries 를 실행시키면 필요한 Golang 바이너리들이 설치된다 (바이너리 업데이트는 :GoUpdateBinaries). 여기까지 오면 준비 끝이다.
  3. Go 소스 탐색
    • hello.go 새로 편집
      vim hello.go를 입력하면 vim-go가 기본 뼈대를 자동으로 만들어 준다.
      package main
      
      import "fmt"
      
      func main() {
        fmt.Println("vim-go")
      }
      
    • <ctrl> ] 입력으로 소스코드 추적
      커서를 Println 구문 위에 놓고 <ctrl>+] 키를 입력하면 fmt.Println() 함수 구현부로 이동한다.
      // Println formats using the default formats for its operands and writes to standard output.
      // Spaces are always added between operands and a newline is appended.
      // It returns the number of bytes written and any write error encountered.
      func Println(a ...interface{}) (n int, err error) {
        return Fprintln(os.Stdout, a...)
      }
      
    • <ctrl> o 입력으로 소스코드 복귀
      다시 <ctrl>+o 키를 입력하면 직전 편집 위치로 복귀한다. <ctrl>+] 키와 함께 쓰면 편하다.
      package main
      
      import "fmt"
      
      func main() {
        fmt.Println("vim-go")
      }
      
끝!


Posted by ingeeC
,