프로그래밍 2019. 8. 28. 11:46 Posted by 정직한 UnHa Kim

나중에 다시 찾아보게 될 것 같아서 기록해 둔다.


PBR = 주가 / 주당순자산 = 주가 / (자본 / 주식수량) = (주가 * 주식수량) / 자본 = 시가총액 / 자본


PER = 주가 / 주당순이익 = 주가 / (순이익 / 주식수량) = (주가 * 주식수량) / 순이익 = 시가총액 / 순이익


PSR = 주가 / 주당매출액 = 주가 / (매출액 / 주식수량) = (주가 * 주식수량) / 매출액 = 시가총액 / 매출액


PCR = 주가 / 주당영업현금흐름 = ...(상동)... = 시가총액 / 영업현금흐름

댓글을 달아 주세요

부동소수점 계산 결과 비교.

프로그래밍 2019. 8. 15. 15:06 Posted by 정직한 UnHa Kim

R에서 개발한 전략을 Go로 포팅하려고 할 때,


최종 결과값이 서로 다르게 나오면, 


계산 과정의 중간값을 비교하면서 오류가 발생한 부분을 찾는 작업이 필요한 데,


R과 Go는 같은 공식에서도 부동소수점 연산 결과가 정말 미세하게 다르게 나오는 관계로,


직접 비교하기 곤란한 경우가 종종 발생한다.


예> 미세한 차이로 인해서,  조건문에서 판단이 다르게 나오는 경우.



그럴 경우 쓸 수 있는 팁 몇 가지를 기록해 둔다.


(나중에 나 스스로 다시 봐야할 것 같은 느낌. 인간의 망각의 동물이더라..)


1. 반올림 해서 미세한 값이 차이는 없애버린다.


2. 크게 변하지 않는 값의 경우에는 테스트할 동안 상수로 고정시켜 버린다.


3. R의 중간값 계산결과를 csv로 저장한 후, Go에서 csv로 불러들여서 대체해 버린다.


가장 확실한 방법은 3번인 것 같다.


예를 들면, A -> B -> C의 과정을 거쳐서 계산을 하는 경우,


C 계산 결과가 뭔가 이상하다고 느껴지는 데,


원인이 A에 있는 지, B에 있는 지 명확하지 않을 경우,


A과정을 R의 계산값으로 대체시켜 버린 후 B의 계산값을 비교하고,


B과정을 R의 계산값으로 대체시켜 버린 후 C의 계산값을 비교하면,


어디에서 포팅 오류가 있는 지 확인할 수 있다.


알고보면 간단한 데, 생각이 안 날 때는 온갖 고생을 겪게 되는 미세한 팁.








댓글을 달아 주세요

COM 스터디 요약 정리

프로그래밍 2018. 5. 16. 13:25 Posted by 정직한 UnHa Kim

리뷰했던 DCOM 관련 서적을 읽은 내용 요약.


COM interface : contract regarding a provided service

IID : interface identifier. a 128-bit globally unique identifier(GUID).

IUnknown : All COM interface must be derived from. (necessary)
IUnknown.QueryInterface : the method used for 'dynamic discovery' of another interface from the object.
IUnknown.AddRef : Object reference count is incremented for management of an object's life cycle.
IUnknown.Release : Object reference count is decremented for management of an object's life cycle.

vtbl : table of function pointers. only a single vtbl exists per class. (not instance)
vptr : pointer to a vtbl (in each instance)

type library : the storage where all the type information of an object is stored
tlb : conventional separated type library file. embedded & integrated in DLL, OCX file.

IDispatch : support dynamic invocation. (optional)
dispatch interface. contains 'a dispatch identifier' (dispid) that aliases an actual method.
'dispid' also can be dynamically discovered through lookup operation.

IConnectionPoint : supports event notification. (optional)

Event : COM supports events via a concept called 'connection points' between 'source' and 'sink'(client).

Basics of COM
1. COM interface : a number of related methods
2. COM object : implements a number of interfaces, must implement 'IUnknown'
3. COM class factory : special COM object that creates or instantiates other COM objects

CLSID : class ID. Like interfaces, libraries, a COM class have unique UUID, specifically called CLSID.

HRESULT : Every COM interface method returns an HRESULT.  (32bit value composed of 4 different parts.)

1. Severity : Was the call successful? 1bit answer. 0 : success, 1 : failure
2. Reserved : 2bits that must be always 0. (Don't mess with it)
3. Facility : Who generated the error? 13bits facility code (indicating RPC, Win32, DISPATCH, etc...)
4. Code : What actually happened? 16bits return code specific to a facility

FACILITY_NULL includes a number of generic and convenient status codes.
Some of these status codes include:
- S_OK : Success
- S_FALSE : False
- E_UNEXPECTED : Unexpected, can be a catastrophic failure
- E_NOTIMPL : Method not implemented
- E_OUTOFMEMORY : Errors dealing with memory allocations
- E_NOINTERFACE : Interface not supported, used in QueryInterface
- E_POINTER : Invalid pointer
- E_FAIL : Generic error, no details available

COM supports a finite list of data types for arguments.
Base Data Types : boolean, byte, char, wchar_t, float, double, small, short, long, hyper, IUnknown*

Extended Data Types (dynamic invocation(=Automation) compatible)
- VARIANTS : a universal data type. technically a union of a bunch of special data types.

3 names for an interface
- GUID (IID_Ixxx) : uniquely identifies an interface
- class or structure name (Ixxx)
- human readable name (xxx.1)

IDispatch supports dynamic invocation but may suffer performance problem from extensive lookup.
For performance, there are other type of invocation the 'dual interface'.

Very Early Binding (vtbl binding)
Client need to be compiled with a given header file generated by MIDL.
Calls are made directly via pointers and gives maximum performance.

Early Binding (static invocation through IDispatch)
Require prior knowledge of 'dispid's.
Development tools can obtain these 'dispid's from a type library.
Since the 'dispid's are already resolved, clients don't have to call GetIDsOfNames,
which means you no longer have the performance hit of looking up 'dispid's.

Bidirectional communication.
- Client can talk to a server by calling an interface
- Server can "call back" to the client to notify them of "events" that are of interest. (Event Source)
- Implement COM object on the client side that exposes a callback interface for the server's use. (Event Sink)

Standard interfaces to support bidirectional communication through call back.
- IConnectionPointContainer
- IConnectionPoint

HRESULT IConnectionPointContainer.EnumConnectionPoints([out] IEnumConnectionPoints **ppEnum)
HRESULT FindConnectionPoint([in] REFIID riid, [out] IConnectionPoint **ppCP)

- Knows about all connection points(IConnectionPoint) that the "event source" supports.
- Client can use the IConnectionPointContainer interface to ask the object whether it supports a particular connection point.
- Client also can use this interface to enumerate (via IEnumConnectionPoints) all the connection points supported by the source object.

HRESULT GetConnectionInterface([out] IID *piid)
HRESULT GetConnectionPointContainer([out] IConnectionPointContainer **ppCPC)
HRESULT Advise([in] IUnknown *pUnkownSink, [out] DWORD *pdwCookie)
HRESULT Unadvise([in] DWORD dwCookie)
HRESULT EnumConnections([out] IEnumConnections **ppEnum)

- This interface allows a sink to call Advise to signal that it is interested in receiving callbacks.
- The connection point object is not the same object as the server COM object that implements the IConnectPointContainer interface.

Given these two standard interfaces, an event source is responsible for following:
1. Implementing the standard IConnectionPointContainer interface.
   This interface allows the sinks to enumerate or find connection points supported by the event source.
2. Implementing the standard IConnectionPoint interface for each outgoing interface.
   This is done to allow the event sink to establish a connection with the source.
   During connection, the sink sends a callback interface pointer to the source,
   so that the source can later make callbacks.
3. Calling back to the registered event sink.

An event sink is responsible for following:
1. Implementing the event sink object so that the event source can make callbacks.
2. Notifying the event source that it is interested in receiving events.
   A sink typically requests the IConnectionPointContainer interface from the event source
    and calls FindConnectionPoint to make sure that the
    event source supports the callback interface implemented by the event sink.
   This will return an IConnectionPoint interface pointer associated with the callback interface.
   A sink then uses the returned IConnectionPoint interface pointer to call Advise.
   In this method invocation, the sink sends a pointer to the its own callback interface to the event source.
   When this invocation returns, the sink will receive a registration cookie.
3. When a sink object no longer wants to receive events associated with the callback interface,
    it must notify the event source of this withdrawl by calling Unadvise using the registration cookie,
    received from calling Advise.

An event source can be thought of as a container that holds a bunch of connection point

댓글을 달아 주세요

64비트 환경에서 32비트 COM 컴포넌트 사용하기.

프로그래밍 2018. 5. 16. 13:21 Posted by 정직한 UnHa Kim
수정> 이 방식으로 COM 함수를 호출하는 것은 잘 되지만, 
        COM이 발생시키는 이벤트를 수신하고 처리하는 게 잘 안 된다.
        Xing API에서는 이러한 이벤트 처리가 필수적이어서,
        이 방안은 더 이상 사용하지 않는다.

인터넷에서 발견한 유용한 팁 번역해서 공유.

32비트 COM객체는 64비트 환경에서 사용하려고 하면, "class not registered"(등록되지 않은 클래스) 에러가 발생한다.

이 문제는 dllhost를 중간에 매개역할을 하도록 하여서 해결할 수 있다.

이를 위해서는 레지스트리 값 몇 개를 수정해야 한다.

  1. COM객체의 GUID를 'HKey_Classes_Root\Wow6432Node\CLSID\[GUID]'에서 찾아낸다.
  2. 찾아낸 후에 REG_SZ (string) 값을 추가한다. 이름은 'AppID', 값은 방금 찾아낸 COM객체 GUID이다.
  3. 'HKey_Classes_Root\Wow6432Node\AppID\' 아래에 새로운 키를 생성한다. 새로운 키의 이름은 COM객체의 GUID이다.
  4. 새로운 키 아래에 REG_SZ (string) 값을 추가한다. 이름은 'DllSurrogate', 값은 공백으로 남겨둔다.
  5. 'HKey_Local_Machine\Software\Classes\AppID\' 아래에 . 이것 또한 새로운 키는 COM객체의 GUID이어야 한다. 이 키 아래에는 새로운 값을 추가할 필요가 없다.

원문 :

When trying to use old components and APIs, developer may face the following problem: 32bit COM objects are not usable in a 64bit environment. Attempt to access a 32bit COM in a 64bit environment will result "class not registered" error. However this issue can be resolved by using dllhost as a surrogate for the 32bit COM object.

Implementation of this fix involves a number of simple registry modifications:

  1. Locate your COM object GUID under the HKey_Classes_Root\Wow6432Node\CLSID\[GUID]
  2. Once located add a new REG_SZ (string) value. The name must be AppID and data must be the same COM object GUID you have just searched for
  3. Add a new key under HKey_Classes_Root\Wow6432Node\AppID\ The new key must be called the same as GUID of the COM object
  4. Under the new key you've just added, add a new REG_SZ (string) value, and call it DllSurrogate. Leave the value empty.
  5. Create a new key under HKey_Local_Machine\Software\Classes\AppID\. Again the new key must be called the same as the COM object's GUID. No values are necessary to be added under this key.

댓글을 달아 주세요

Go언어에 짙게 배인 Pascal 향기.

프로그래밍 2018. 5. 16. 11:04 Posted by 정직한 UnHa Kim

GUI 개발을 간편하게 할 수 있는 방안을 알아보던 중,

무료 Delphi 대체재 'Free Pascal + Lazarus'를 알게 되었다.

Object Pascal 언어 가이드를 구해서 읽어보니, Go언어 문법과 비슷한 부분이 너무나 많이 보인다.

Go언어가 Pascal의 영향을 아주 많이 받은 것이라고 추정된다.

기억에 남는 몇 가지만 예로 들면

1. 변수 선언 방식 :  <변수명>: <자료형>;    여기에서 ':', ';'만 빼면 Go자료형 선언과 같아진다.

2. 변수 대입 : ':=', Go언어에서 변수 생성 및 대입을 겸하는 연산자와 같은 모양.

3. 정적 배열 : 정적 배열의 길이별로 독립된 자료형이라는 점이 동일하다.

4. 동적 배열 : 정적 배열과 별개로 동적 배열 (Go언어는 slice라고 부른다.)이 존재하는 점이 동일.

기타, 여러가지 면에서 Pascal언어 책을 보고 있는 것인지, Go언어 책을 보고 있는 것인지 헷갈릴 정도로 익숙한 점이 많았다.

Go언어에 익숙해 지고 나니, 'Free Pascal + Lazarus'에 대한 친근감과 호감도가 급상승한다.

댓글을 달아 주세요

Go 1.10 컴파일 속도 개선.

프로그래밍 2017. 12. 21. 12:47 Posted by 정직한 UnHa Kim

Go언어 공식 웹사이트에 1.10 베타 버전이 업로드 되었다.

이번 버전 역시 개인적인 최대 관심사는 Go언어 컴파일러가

버전 1.4까지 C언어로 작성되었다가

버전 1.5부터 Go언어로 변경되면서 느려진 컴파일 속도가

얼마나 다시 빨라질 것인가 이었다.

애초에 Go언어를 선택한 중요한 이유 중 하나가

엄청나게 빠른 컴파일 속도 덕분에 인터프리터 언어 못지 않은 작업 생산성이 나온다는 것이었고,

버전 1.5 이후 2배 가까이 느려진 컴파일 속도와 더불어서

프로젝트에서 사용하는 외부 라이브러리도 많아지면서

컴파일 시간이 늘어나면서 작업 생산성이 떨어졌기 때문이었다.

1.10 버전에서 가장 큰 개선점은 빌드 캐쉬로 인한 컴파일 속도 개선이다.

의존성 라이브러리를 비롯한 모든 소스코드는 컴파일 결과가 캐쉬(임시 저장)되며,

파일 수정날짜에 상관없이 오직 내용 변경여부 만으로 재컴파일 여부를 결정한다.

1번째 컴파일은 여전히 느리지만,

2번째 컴파일부터는 변경된 소스코드만 컴파일 하므로,

컴파일 작업량이 대폭 줄어들면서 속도가 확연하게 빨라진다.

대개 인간의 집중력 유지 시간은 15초를 넘기지 못한다.

여러 단점에도 불구하고 인터프리터 언어가 높은 생산성을 보여주는 이유는

컴파일 과정이 존재하지 않으므로,

'수정-실행' 작업 루틴 중 집중력이 유지되는 이유가 크다.

예전에는 소스코드 수정 후 테스트 실행하면 10초 넘게 빌드되기를 기다려야 되다보니,

집중력이 떨어지고, 작업 흐름이 끊기는 게 느껴졌지만,

1.10부터는 빌드 타임이 짧아지면서 그 정도가 낮아졌다.

즉, 집중력이 유지되면서 작업 흐름이 끊기지 않고 계속 이어진다.

높아진 작업 생산성을 체감하면서 이 글을 쓰고 있다.

드디어 마지막 C언어로 작성되었던 Go 언어 버전 1.4를 떠나보낼 수 있게 되었다.

댓글을 달아 주세요

Go언어 에러처리

프로그래밍 2016. 11. 2. 10:11 Posted by 정직한 UnHa Kim

Go언어를 쓰면서 느끼는 가장 큰 불편은 '에러처리'이다.

try-catch 같은 예외처리 기능이 없으며,  if문(!)에서 에러발생 여부를 확인해야 한다.


if 반환값, 에러 := F실행할_함수(인수1, 인수2....); 에러 != nil {

<여기에서 에러처리....>


이 방식은 소스코드가 지저분해지는 문제점이 있다.

1. 실행할_함수()는 if문에 파묻혀서 잘 보이지 않는다.

2. 소스코드가 지저분해진다. 소스코드 중간중간에 if문이 끼어들어서 흐름을 끊어놓는다.

그럼에도 불구하고 장점도 있다.

1. 예상하지 못한 동작이 발생하는 것이 예방된다. -> 오작동이 치명적인 경우에는 장점이 된다.

2. 각 에러마다 정확한 개별 대응이 쉽다.

이런 장점에도 불구하고, if문을 사용하는 에러처리 패턴이 불편하게 느껴지는 것은 사실이다.

defer, recover, panic을 조합하면 예외처리 기능처럼 에러를 뭉뚱그려서 한 번에 처리할 수 있다.

try-catch문은 예외가 발생하면 실행이 중단되고, catch문 내용이 실행된다.

Go언어에서는 패닉이 발생하면 실행이 중단되고, defer문으로 등록한 함수가 실행된다.

try문에서 예외가 발생해도 catch문에서 적절한 처리를 해준다면 프로그램 실행이 중단되지 않고 계속 실행된다.

패닉이 발생해도 defer문에 등록한 함수는 실행되며, 그 부분에서 recover함수를 호출한다면, 프프로그램 실행이 중단되지 않고 계속 실행된다.

실행 흐름은 '에러발생->패닉발생->defer->recover->에러처리' 로 이루어진다.


func F함수_정의(인수A, 인수B,...) {

defer func() {    // 3함수 실행이 종료될 때 자동으로 실행된다. 패닉이 발생해도 실행된다.

if r := recover(); r != nil {    // 4recover함수를 실행해서 패닉된 경우 복구한다.

<여기에서 뭉뚱그려서 에러처리>




반환값, 에러 := F실행할_함수(인수1, 인수2....)

if 에러 != nil {    // 1 : 에러가 발생하면 패닉을 발생시켜서 함수의 실행을 종료하도록 한다.

panic(에러)    // 2  :  패닉이 발생하면 실행이 중단되고,  defer로 함수로 넘어간다.





언뜻 보면 소스코드가 오히려 더 복잡해진 느낌이다.

그러나, 다음 2개의 도우미 함수를 사용해서 반복되는 부분을 제거할 수 있게 된다.


func F에러2패닉(에러 error) {

if 에러 != nil {    // 에러가 발생하면 패닉 되도록 한다.




func F패닉_처리(함수 func(r interface{}) {

if r := recover(); r != nil {    // 패닉이 발생한 경우 패닉을 복구하고 지정된 함수를 실행한다.




도우미 함수를 이용해서 소스코드를 간단하게 수정하면 다음처럼 된다.

func F함수_정의(인수A, 인수B,...) {

defer F패닉_처리(func(r interface{}) {

<여기에서 뭉뚱그려서 에러처리>



반환값1, 에러 := F실행할_함수_1(인수1, 인수2....)

F에러2패닉(에러)    // 에러는 패닉으로 전환되고, defer에 등록된 패닉처리 함수가 실행됨.


// 여기까지만 보면 크게 좋은 점을 모르겠으나, 

// 처리해야 할 에러가 많아지면 이러한 방식의 장점이 드러난다.


반환값2, 에러 := F실행할_함수_2(인수1, 인수2....)



반환값3, 에러 := F실행할_함수_3(인수1, 인수2....)





타 언어의 try-catch 방식의 예외처리문보아야 여전히 불편하긴 하지만,

if문을 사용해서 모든 에러를 일일이 확인하는 기존의 방식보다는 훨씬 간편하다.


Go언어는 예외처리도 if문으로 대체할 정도로 최소한의 기능만을 가지고 있는 대신,

언어가 간단해서 배우기 쉽고, 다른 사람의 소스코드를 읽기도 쉬우며,

컴파일 속도가 빨라서 코딩 및 디버깅 생산성도 높고,

소스코드를 자동으로 정리해 주는 기능도 존재한다.


Go언어를 처음 접하면 컴파일 속도를 빼면 어느 것 하나 특출난 것 없이,

이것 저것 부족한 기능이 불편하게 느껴지지만,

쓰면 쓸 수록 

- 꼭 필요한 것은 다 있는 기능성.

- 높은 개발 생산성

- 빠른 실행속도

3가지 요소가 골고루 균형 잡혀있는 것에 감탄하게 된다.

댓글을 달아 주세요

한글로 된 Go언어 입문서 소개

프로그래밍 2015. 9. 11. 10:07 Posted by 정직한 UnHa Kim

한글로 된 Go언어 책이 발간되었길래 구입해서 읽어보니 분량도 많지 않고 내용도 상당히 알차다.

부동소숫점끼리 비교할 때는 '=='를 사용하면 안 된다는 부분을 읽으면서 예전에 고생했던 기억이 새록새록 나면서 저자의 내공을 느꼈다.

막연히 멀게만 느껴졌던 클로저에 대한 개념, 유용성, 활용법등도 아주 쉽게 설명해 놨다.

저자는 쉽고 간결하게 설명하는 재주가 있는 듯 하다.

개념을 완전히 소화해서 자기 것으로 만든 후에야 가능한 경지가 아닐까 싶다.

책 제목은  가장 빨리 만나는 Go 언어

Go언어는 한국에서는 아직 비주류이라서 한글로 된 서적을 구하기 쉽지 않은 데,

이 책이 Go언어에 입문할 때 많은 도움이 될 듯 하다.

댓글을 달아 주세요

Go언어 소개

프로그래밍 2014. 11. 4. 20:55 Posted by 정직한 UnHa Kim

Go언어는 효율성을 추구하는 실용적인 프로그래밍 언어이다.

1. 개발 생산성

2. 멀티코어 CPU 하드웨어 사용의 효율성

2가지를 모두 추구하는 대신 기능성은 포기했다.

Go언어의 창시자는 C++언어의 복잡성에 학을 떼고, 

공개적으로 미니멀리즘을 추구한다고 하는 데,

어쩔 때는 그게 좀 과한 듯 하다.

(키워드 숫자를 줄이려고 interface가 가변형 자료형을 겸하는 것은 조금 오버이고,

 에러처리도 if문으로 처리한다는 것은 소스코드를 번잡하게 만든다.) 

개발자 생산성 향상을 위해서는 다음 특징을 가진다.

1. 빠른 컴파일.

2. 단순하지만 필수기능은 다 갖춘 문법.

3. 자동 메모리 관리

4. 유니코드 지원

5. 풍부한 표준 라이브러리 및 수많은 제3자 공개 라이브러리.

6 테스트, 테스트 커버리지, 동시 사용 데이터 충돌(레이스) 감지등 풍부 개발 도구 기본 내장


7. 소스코드 자동 정리 (써보면 입이 떡 벌어진다.)

하드웨어의 효율적 사용을 위해서 다음 특징을 가진다.

1. AOT 컴파일. (C, C++의 컴파일 개념. Java나 C#이 사용하는 JIT컴파일의 반대 개념.)

2. C보다 2배 정도 느리고, Java와는 비슷한 단일 스레드 실행 속도.

3. 멀티코어 CPU를 안전하고 효율적으로 사용하기 위한 독특한 기능 (goroutine, channel)

Go언어에서는 포기한 기능들은 다음과 같다.

1. 상속은 지원하지 않음. 대신 mixin을 지원.

2. 제너릭은 지원하지 않음. 대신, interface{}가 가변형 변수 역할을 함.

(제너릭 기능은 Go언어 창시자들이 미니멀리즘에 기반하여 의도적으로 배제한 것이 아니라,

 Go언어 창시자들이 기술적인 문제를 해결하지 못해서 아직 추가되지 못한 경우임.)

3. 에러처리 구문이 취약함. 대신, defer문, recover()함수를 사용해서 panic상황에 대처 .

이러한 장단점이 혼합된 Go언어를 실제로 사용해 본 느낌과,

1. 기능성이 약간 부족하지만 오히려 간결해서 좋은 면도 있다.

   기능이 풍부하지 않지만 꼭 있어야 하는 기능들은 거의 다 있으며,

   반대로, 쓸데없는 기능이 없기 때문에 남이 개발한 소스 코드를 읽을 때도

   처음보는 기능을 접하는 경우는 거의 없다.

   그래서, 불러다 쓰는 제 3자 라이브러리가 의심스러우면 

    (저작권 문제가 없는 한도 내에서) 거리낌없이 소스 코드를 들여다보고 만지작 거리게 된다.

2. 개발 생산성이 확연하게 높아진다.

3. 실행속도 문제로 걱정할 일이 없다.

트위터가 서비스 초기에 루비(Ruby)언어를 사용했으나, 성능 상의 문제로 인해서 서비스 불안정의 어려움을 겪었고, 결국은 상당 부분을 Java와 Scala언어로 다시 개발해야 했다.

드롭박스도 서비스 초기에 파이썬(Python)언어를 사용했으나, 성능 상의 문제로 인해서 일부분을 Go언어로 대체하였다.

트위터와 드롭박스의 공통점은 높은 개발 생산성을 얻기 위해서

루비(Ruby), 파이썬(Python)등 동적언어를 사용하였으나,

성능상의 문제로 인해서 동일한 기능을 정적 언어로 다시 작성했다는 것이다.

Go언어는 성능이 상당히 좋으므로 

한 번 개발해 놓으면, 성능 문제 때문에 다시 개발해야 할 필요성이 적으며,

개발 과정에서도 비교적 높은 개발 효율성을 얻을 수 있다.

무한 경쟁 시대에 비용 효율성 면에서 강점을 가진다.

(구글이 비용 절감 차원에서 만든 것 같다.)

그 대신에 포기해야 하는 것이 기능성인데, 

막상 써보면 기능이 심하게 부족하다고 느껴지지는 않는다.

물론, C++, Java, C#등을 사용하던 사람은

1. 변수 선언 순서가 반대임.

2. 에러 처리 구문이 없고 if문으로 처리함.

3. 제너릭이 없음

등의 장애물에 좌절하곤 하지만 

실제로 사용해보면 의외로 그럭저럭 쓸만 하다.

(Java도 1.4까지 Generic이 없었지만 다들 잘만 쓰더라.)

Go언어를 가장 잘 설명하는 문구는  '모든 면에서 80%'이다.

파이썬(혹은 루비) 개발 효율성의 80%,

C++ 실행 효율성의 80% (사실은 50%이지만, 동적 언어보다 수백배 빠르므로 체감상 80%)

모든 면에서 약간씩 부족하고 아쉽지만,

비용절감의 면에서는 타의 추종을 불허하고,

여러모로 공동작업이 편하다.

소스코드 1천 라인은 0.2초, 12만 라인은 9.2초만에 컴파일 하는 것을 보여주는 동영상.

Go언어의 무시무시한 컴파일 속도를 체감할 수 있다.

실제로 사용해 보면 파이썬 같은 동적언어를 쓰고 있는 지, 정적 컴파일 언어를 쓰고 있는 지 헷갈림.

동영상 원본 링크 :


TAG go언어

댓글을 달아 주세요