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
- go - Golang pointers - Stack Overflow
- Frequently Asked Questions (FAQ) - The Go Programming Language
댓글 없음:
댓글 쓰기