Call by value와 Call by reference

 

Call by value

type a struct {
	value int
}

func run(aa,bb a) {
	aa.value = 111
	bb = aa
	fmt.Println(aa, bb)
}

func main()  {
	a1 := a{value: 1}
	a2 := a{value: 2}

	run(a1,a2)
	fmt.Println(a1, a2)
}

결과

{111} {111}
{1} {2}
  • run 함수 내부에서는 변경이 되지만 외부까지 변경이 전파가 되진 않는다.
    • 그 이유는 run 함수 내부의 파라미터가 실제 객체를 복사한 값을 사용하기 때문
    • 이 방식이 Call by Value

 

 

Call by reference

  • 하지만 Go 에서는 Call By Value 대신 Call By Referece도 사용할 수 있는데
  • 그 방법은 바로 Pointer를 사용하는 방법이다
type a struct {
	value int
}

func run(aa,bb *a) {
	aa.value = 111
	bb = aa
	fmt.Println(aa, bb)
}

func main()  {
	a1 := a{value: 1}
	a2 := a{value: 2}

	run(&a1,&a2)
	fmt.Println(a1, a2)
}

결과

&{111} &{111}
{111} {2}
  • run 함수 내부의 변경이 외부까지 전파가 되었다.
    • 하지만 bb 파라미터의 변경은 외부에 전파가 되지 않았다. 그 이유는 뭘까 ?
      • 내부 파라미터 자체를 변경했기 때문이다.
      • 실제 객체를 변경하는 것이 아닌 파라미터에 할당한 값이 bb의 주소에서 aa의 주소로 변경 된것일 뿐이다.

 

 

자바와 다른점

  • java는 Call by value 지만 객체를 넘겼을 경우 객체 내부의 변경이 외부에 전파가 된다.
  • 이는 파라미터로 객체를 전달시에 객체의 주소를 넘기기 때문이다.
    • 주소를 넘김으로써 주소가 가리키는 객체가 외부의 객체가 되고 변경의 여파가 외부까지 전파되는 것이다.

 

 

파라미터에 Pointer를 사용하는 경우

  • 보통 Pointer를 사용시 내부에서의 변경이 외부까지 전파가 되므로 최대한 사용을 자제하는 방향이다.
  • 하지만 객체가 생성비용이 비싼 경우 Call by value로 복사를 하므로 생성비용이 과하게 나오는 경우가 생긴다.
  • 이런 경우 Pointer를 사용하여 객체 생성비용을 절약할 수 있다.

+ Recent posts