• Home
  • About
    • Jiwon Jeong photo

      Jiwon Jeong

      끊임없이 배우며 성장하는 엔지니어

    • Learn More
    • Email
    • Github
  • Posts
    • All Posts
    • All Tags
    • All Categories
  • Projects

(매우 중요!!)Go 포인터 리시버 사용법과 패키지 간 구조체 리턴 방법

15 Dec 2021

Reading time ~3 minutes

Go 포인터 리시버 사용법

package main

import (
	"fmt"
)

type BlockInfo struct {
	TotalBlocks int
	MaxID       int
	MinID       int
}

func (b *BlockInfo) PointerReceiver(num int) *BlockInfo {
	b.TotalBlocks = num
	return b
}

func PointerParam(b *BlockInfo, num int) *BlockInfo {
	b.TotalBlocks = num
	return b
}

  • PointerReciver 함수는 포인터 리시버가 있는 메소드
    • BlockInfo 혹은 BlockInfo 포인터로 접근할 수 있다.
      • 원리 : 포인터 리시버는 값(value)과 포인터 모두 접근 가능
      • 이 의미는 다음 코드와 같다.
func main() {
	bl := BlockInfo{} // 구조체 자체로 접근
	res1 := bl.PointerReceiver(2)
	fmt.Println("PointerReciver 함수를 BlockInfo로 접근했을 때의 결과는 ", res1.TotalBlocks)

	b2 := &BlockInfo{} //구조체 포인터로 접근
	res2 := b2.PointerReceiver(2)
	fmt.Println("PointerReciver 함수를 BlockInfo 포인터로 접근했을 때의 결과는 ", res2.TotalBlocks)

}
// 결과
// PointerReciver 함수를 BlockInfo로 접근했을 때의 결과는  2
// PointerReciver 함수를 BlockInfo 포인터로 접근했을 때의 결과는  2

  • PointerParam 함수는 포인터 인자가 있는 함수
    • BlockInfo 포인터만 인자로 들어올 수 있음
      • BlockInfo 구조체 자체는 인자로 쓸 수 없음!
      • 원리 : 포인터를 인자로 받는 함수는 값(value)을 전달받을 수 없고, 값(value)을 인자로 받는 함수는 포인터를 전달받을 수 없다
      • 아래 두개의 print함수는 결국 똑같이 포인터로 받기 때문에 그 의미는 같음
func main() {
	bl := BlockInfo{}
	res3 := PointerParam(&bl, 2)
	fmt.Println("PointerParam 함수의 파라미터를 포인터로 받은 결과는 ", res3.TotalBlocks)

	b2 := &BlockInfo{}
	res4 := PointerParam(b2, 2)
	fmt.Println("PointerParam 함수의 파라미터를 포인터로 받은 결과는 ", res4.TotalBlocks)

}
  • 여기서 주의점 : PointerReciver 함수는 b1.PointerReceiver(2), PointerParam 함수는 앞에 b1.으로 접근하지 않는다!

응용

Account 구조체의 Num 값 변경하기

  • 아래 코드의 결과는 CallByValue로 쓰였기에, 값이 5가 나옴
package main

import "fmt"

type Account struct {
	DOCTYPEID string `json:"@account"` // address
	Token     string `json:"token"`
	Num       int
}

func res(account Account, plus int) int {
	account.Num += plus
	return account.Num
}

func res2(account Account, plus int) int {
	account.Num += plus
	return account.Num
}

func main() {
	var ans int
	a1 := Account{}
	ans = res(a1, 3)
	ans = res2(a1, 5)
	fmt.Print(ans) // 5
}
  • 하지만, 아래 두개의 코드는 똑같은 결과가 도출되며, CallByReference(포인터)를 사용했기에, 기존 3에 5를 더한 8이라는 값이 나옴
package main

import "fmt"

type Account struct {
	DOCTYPEID string `json:"@account"` // address
	Token     string `json:"token"`
	Num       int
}

func res(account *Account, plus int) int {
	account.Num += plus
	return account.Num
}

func res2(account *Account, plus int) int {
	account.Num += plus
	return account.Num
}

func main() {
	var ans int
	a1 := &Account{}
	ans = res(a1, 3)
	ans = res2(a1, 5)
	fmt.Print(ans) // 8
}

package main

import "fmt"

type Account struct {
	DOCTYPEID string `json:"@account"` // address
	Token     string `json:"token"`
	Num       int
}

func res(account *Account, plus int) int {
	account.Num += plus
	return account.Num
}

func res2(account *Account, plus int) int {
	account.Num += plus
	return account.Num
}

func main() {
	var ans int
	a1 := Account{} // 이 부분 변경
	ans = res(&a1, 3) // 이 부분
	ans = res2(&a1, 5) // 이 부분
	fmt.Print(ans)
}

Go 패키지 간 구조체 리턴 방법

  • Go에서 가시성 옵션 (Public, Private…) 등은 함수, 구조체의 대문자 및 소문자로 구분한다.
    • 외부에서 사용할 때 : 함수와 구조체의 첫글자는 대문자로 설정해주어야 한다!
  • 목표 : templib 패키지의 GetMethod 함수를 메인함수에서 호출하고자 할때 다음과 같은 방식으로 구현해주면 된다.
package templib

type BlockInfo struct {
	TotalBlocks int
	MaxID       int
	MinID       int
}

func (b *BlockInfo) PointerReceiver(num int) *BlockInfo {
	b.TotalBlocks = num
	return b
}

func PointerParam(b *BlockInfo, num int) *BlockInfo {
	b.TotalBlocks = num
	return b
}

package main

import (
	"fmt"
	"templib"
)

func main() {
	bl := templib.BlockInfo{} // 구조체 자체로 접근
	res1 := bl.PointerReceiver(2)
	fmt.Println("PointerReciver 함수를 BlockInfo로 접근했을 때의 결과는 ", res1.TotalBlocks)

	b2 := &templib.BlockInfo{}
	res4 := templib.PointerParam(b2, 2)
	fmt.Println("PointerParam 함수의 파라미터를 포인터로 받은 결과는 ", res4.TotalBlocks)
}

// 결과
// PointerReciver 함수를 BlockInfo로 접근했을 때의 결과는  2
// PointerParam 함수의 파라미터를 포인터로 받은 결과는  2


개발일기 Share Tweet +1