type Dog struct {
}
func (d Dog) run() {
println("run")
}
dog1 := &Dog{} // type: *Dog
dog1.run()
dog2 := Dog{} // type: Dog
dog2.run()
C나 C++을 배운 사람에게는 상당히 이상한 코드이다!
고랭에는 화살표 연산자가 없어서, 포인터도 일반 객체처럼 행동할 수 있다.
func MyFunction(dog1 Dog, dog2 *Dog) {
// do something
}
MyTest(*d1, &d2)
포인터 객체인지, 일반 객체인지에 따라 함수 paramter에 맞춰서 넣어주어야 한다.
객체에서 포인터는 일반 객체와 명백히 다른 타입이며,
화살표 연산자가 없어 객체처럼 행동한다.
이제 헷갈리는 건 interface에서 pointer가 결합되었을 때이다. Dog와 같은 동물을 추상화한 Animal interface
를 추가해보자.
type Animal interface {
run()
}
type Dog struct {
}
func (d Dog) run() {
println("run")
}
Animal interface에 정의된 함수를 구현했으므로, Dog는 Animal의 구현체가 된다.
animal1 := Dog{}
animal2 := &Dog{}
animal1Type := reflect.ValueOf(animal1).Type() // Dog
animal2Type := reflect.ValueOf(animal2).Type() // Dog
if animal1Type == animal2Type {
println("animal1과 animal2는 서로 같은 타입니다.")
}
이런 현상이 가능한 이유는 interface 속이 생긴 구조 때문이다.
interface 데이터 형식
자세한 건 나중에 알아보기로 하고 여기서 중요한 건 interface 내부에는 포인터가 저장된다는 사실이다. 그냥 value를 넣어주어도 내부에서는 주소를 저장하기 때문에, 주소를 넣어준 것과 같은 효과라는 것이다.
type Animal interface {
run()
}
type Dog struct {
}
//func (d Dog) run() {
// println("run")
//}
func (d *Dog) run() {
println("run")
}
Dog 객체가 Value Receiver가 아닌 Point Receiver로 함수를 구현했다고 바꾸어보자.
var animal Animal
animal = Dog{} // nope
animal = &Dog{} // ok
var dog Dog = Dog{} // ok
animal = Dog{}
여기서에는 Cannot use 'Dog{}' (type Dog) as type Animal Type does not implement 'Animal' as 'run' method has a pointer receiver 라는 이유로 오류가 생긴다.
Pointer receiver 함수를 접근하기 위해서는 dog의 포인터가 필요한데 그게 없어서라고 생각이 되는데, 어차피 interface 내부에서는 포인터를 가지고 있으니 상관없지 않나? 아직 잘 모르겠음