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함수는 결국 똑같이 포인터로 받기 때문에 그 의미는 같음
- BlockInfo
- BlockInfo
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