[Golang] Linked List 자료구조

Golang은 (고랭지 배추가 생각나..) 기본적으로 데이터 컨테이너로 배열(Array), 슬라이스(Slice), 맵(Map)을 지원합니다. 이 세개의 데이터 컨테이너는 별도의 라이브러리를 import하지 않아도 사용할 수 있는 goland의 기본 요소입니다. 여기에 추가적으로 Linked List 자료구조는 별도의 라이브러를 import 하여 사용할 수 있는데요. 간단히 아래의 예제 코드를 통해 다른 언어를 통해 링크드 리스트를 접해본 개발자라면 쉽게 이해할 수 있을 것입니다.

package main

import (
    "container/list"
    "fmt"
)

func main() {
    ll := list.New()

    ll.PushBack("A")
    ll.PushBack(100)
    ll.PushBack(true)
    ll.PushFront("B")
    ll.PushFront(200)

    for e := ll.Front(); e != nil; e = e.Next() {
        fmt.Printf("[%T] %v\n", e.Value, e.Value)
    }

    fmt.Println("-------------")

    for e := ll.Back(); e != nil; e = e.Prev() {
        fmt.Printf("[%T] %v\n", e.Value, e.Value)
    }
}

링크드리스트 객체는 list.New() 함수 호출을 통해 생성할 수 있습니다. 데이터를 뒷 부분부터 추가(코드 11번~13번)할 수도 있고, 시작 부분에 추가(코드 14번~15번)할 수도 있습니다. 그리고 코드17번~19번처럼 링크드리스트의 시작부터 끝부분까지 순회할 수 있습니다. 이와 반대 방향으로 순회하는 코드는 23번~25번입니다. 실행 결과는 아래와 같습니다.

[int] 200
[string] B
[string] A
[int] 100
[bool] true
-------------
[bool] true
[int] 100
[string] A
[string] B
[int] 200

golang의 링크드 리스트는 배열이나 슬라이스, 맵과는 다르게 지정된 타입의 값만을 추가할 수 없고 모든 타입에 대한 값을 추가한다는 점에 주의해야 합니다.

[Golang] 함수 실행 시간 측정

golang에는 defer라는 예약어가 있습니다. defer로 지정된 함수 호출은, defer를 호출한 함수의 종료시에 호출되도록 보장한다는 것입니다. 이를 응용해서 함수의 실행 시간을 측정할 수 있는 범용성 있는 함수를 다음 코드처럼 만들 수 있습니다.

func ElapsedTime(tag string, msg string) func() {
    if msg != "" {
        log.Printf("[%s] %s", tag, msg)
    }

    start := time.Now()
    return func() { log.Printf("[%s] Elipsed Time: %s", tag, time.Since(start)) }
}

ElapsedTime 함수는 defer 문과 함께 사용되어야 의미가 있는데요. 이 함수를 호출하면 함수를 반환하게 되는데, 이 반환된 함수가 바로 defer 문을 통해 최종적으로 호출될 함수입니다. 이 함수를 테스트하기 위해 아래처럼 코드를 작성해 보겠습니다.

package main

import (
    "log"
    "time"
)

func bigSlowOperation() int {
    defer ElapsedTime("bigSlowOperation", "start")()

    time.Sleep(10 * time.Second) // 10초 정도 소요되는 연산에 해당하는 코드라 가정

    return 0
}

func ElapsedTime(tag string, msg string) func() {
    // 생략
}

func main() {
    bigSlowOperation()
}

크고 느린 연산를 호출하는 함수인 bigSlowOperation 함수 내부를 보면 defer 문으로 ElapsedTime 함수를 호출하여 반환된 함수를 호출하고 있습니다. 이를 통해 bigSlowOperation 호출이 끝나면 bigSlowOperation의 실행에 소요된 시간을 표시하게 되는데요. 그 결과는 아래와 같습니다.

2016/10/01 22:28:07 [bigSlowOperation] start
2016/10/01 22:28:17 [bigSlowOperation] Elipsed Time: 10.0007115s