[컴][go] c/c++ 의 pointer 와 go 의 pointer 의 차이

golang / pointer variable of golang


c/c++ 의 pointer 와 go 의 pointer


go 에도 pointer 가 존재한다. 개인적으로 c/c++ 언어 이외에 처음본다 ^^;;


처음에 이것은 heap 에서 allocate 하는 메모리를 줄이려고 한줄 알았는데, 그것은 아닌듯 하다.

ref.2 의 글의 번역을 읽어보면 아니라는 것을 알수 있다.
pointer type으로 구현하나 value type 으로 구현하나 그것이 heap 이나 stack 에 가는 것을 결정하지는 않는다. 이 부분은 Go compiler 가 알아서 변수가 함수내에서만 쓰이면 함수의 stack frame 에 넣어준다고 한다. 그러나 compiler 가 함수가 return 한 이후에도 변수가 계속 referenced 되는지 판단하지 못하는 경우라면, compiler 는 이것을 heap 에다 넣는다.
또한 local 변수가 너무 크면, stack 보다는 heap 에 넣는다고 한다.
current compiler 에서는 변수가 자신의 주소를 가지고 있으면, 이녀석은 heap 에 넣을 후보(candidate) 가 되지만, escape analysis 가 이 변수가 function 이 return 한 이후에 살아 있지 않고, stack 에 머무를 수 있다는 것을 파악한다.(이런 녀석은 heap 에 넣지 않는다. 란 뜻인듯)[ref. 2]
다른 가능성 있는 이유들은 아래 글에서 찾아보자.

여하튼 이녀석은 c/c++ 의 pointer 와 거의 유사하다. 그런데 한가지 다른 점은 사용할 때가 좀 다르다.


초기화

초기화는 c/c++ 과 크게 다를 것 없다.  아래처럼 pointer type에서의 intialization 과 value type에서의 intialization 은 다르다.


value 변수의 초기화


// Worker is job thread
type Worker struct {
 name      string
 readyChan chan int
 jobChan   chan interface{}
}


// Pool ...
type Pool struct {
 workers []Worker
}

func NewPool() *Pool {

    numWorkers := 3
    self := &Pool{workers: make([]Worker, numWorkers)}

    for i := 0; i < numWorkers; i++ {
        rc := make(chan int)
        jc := make(chan interface{})
        self.workers[i].readyChan = rc
        self.workers[i].jobChan = jc
    }

    return self
}


pointer 변수의 초기화


// Worker is job thread
type Worker struct {
 name      string
 readyChan chan int
 jobChan   chan interface{}
}


// Pool ...
type Pool struct {
 workers []*Worker
}

func NewPool() *Pool {

    numWorkers := 3
    self := &Pool{workers: make([]*Worker, numWorkers)}

    for i := 0; i < numWorkers; i++ {
        rc := make(chan int)
        jc := make(chan interface{})
        self.workers[i] = Worker{name: "n" + strconv.Itoa(i), readyChan: rc, jobChan: jc}
    }

    return self
}

사용

그런데 사용함에 있어서는 Go 는 좀 더 유연하다. 위의 두가지 initialization 모두 아래처럼 사용할 수 있다.
func main(){
  pool := NewPool()
  go func(){
    pool.workers[0].readyChan <- 1
  }()
  <-pool.workers[0].readyChan
}

그리고 pointer 로 initialization 을 한 code 에서는 아래처럼 code 를 작성해도 된다.
(*pool.workers[0]).readyChan <- 1

이것은 method 를 사용할 때도 마찬가지이다. 만약 아래 처럼 pointer type의 method 를 하나 만들었다고 해도 value type 변수를 사용해서도 사용할 수 있다.
func (v *Worker) do() {}
func main(){
  var w Worker
  w.do()
}


이유

이런 것이 가능한 이유는 ref. 1 에 잘 설명되어 있다. 대략적으로 이야기 하면, go compiler 가 알아서 변경을 해주거나 wrapper function 을 만들어 주기 때문이다.



Reference

  1. go - Golang pointers - Stack Overflow
  2. Frequently Asked Questions (FAQ) - The Go Programming Language





댓글 없음:

댓글 쓰기