go 인터페이스 주의점
3275 단어 go
go interface의 본질이 무엇인지에 대해 인터넷에서 두 개의 바늘을 가진 struct라고 하는데 하나는 실행할 때의 유형을 가리키고 하나는 대상을 가리키는 자체이다
나는 개인적으로 이 견해가 너무 모호하다고 느낀다. 그래도 실제 코드 실험을 하는 것이 좋겠다
type IObject interface {
SetValue(value int)
GetValue() int
}
type Object struct {
Value int
}
func (obj Object) SetValue(value int) {
obj.Value = value
}
func (obj Object) GetValue() int {
return obj.Value
}
func main() {
var obj = Object{Value: 1}
var iObj IObject = obj // * *
obj.Value = 2 // receiver , obj.SetValue(2)
fmt.Println(obj.GetValue()) // "2":
fmt.Println(iObj.GetValue()) // "1":
}
관건적인 조작 * 대상이 인터페이스에 값을 부여하는 것 * 이 실제적으로 값을 복사한 것은 Object 대상 변수 간의 값을 부여하는 효과와 같다는 결론을 얻을 수 있다
생각보다 자바처럼 인터페이스가 대상의 인용이 아니다
만약 이런 효과가 필요하다면, Object 대상의 바늘을 인터페이스에 값을 부여해야 한다
방금 코드를 직접 수정하여 값 부여 문장을 바늘로 값 부여하면 됩니다. 이때 IObject 변수가 값 부여된 것은 Object 대상의 바늘입니다.
type IObject interface {
SetValue(value int)
GetValue() int
}
type Object struct {
Value int
}
func (obj Object) SetValue(value int) {
obj.Value = value
}
func (obj Object) GetValue() int {
return obj.Value
}
func main() {
var obj = Object{Value: 1}
var iObj IObject = &obj // * *, ,
obj.Value = 2
fmt.Println(obj.GetValue()) // "2":
fmt.Println(iObj.GetValue()) // "2":
iObj.SetValue(3) // : SetValue , receiver
fmt.Println(obj.GetValue()) // "2":
fmt.Println(iObj.GetValue()) // "2":
}
또한 주의해야 할 점이 있다. Go는 C++의 바늘 연산자가 없기 때문에 go 언어에서 바늘 연산자를 수치 연산자로 대체했다. 즉, 변수가 대상 자체든 대상의 바늘이든 모두 수치 연산자를 사용했기 때문에 이것은 어떤 영향을 미칠까?C++의 프로그래머로서 곤란함을 느낄 수 있습니다. 현재 저는 두 가지를 정리했습니다.
1. 모든 구성원을 뽑는 작업은 일괄적으로 처리된다. 이것도 기본이다. 변수가 대상이든 지침이든 직접 구성원을 뽑는 조작부호로 접근할 수 있다. 구성원은 필드와 방법을 포함한다.
2. 모든 부치와 전참의 부분은 민감한 처리를 필요로 한다. 바늘부호 바늘, 대상부호 대상, 바늘이 대상에게 부치려면 내용을 취해야 한다(C++와 같고 * 연산자), 대상이 바늘에 부치면 주소를 취해야 한다(C++와 같고 & 연산자), 함수 전참도 마찬가지로 이 규칙을 따라야 한다.
그럼 곰곰이 생각해 보세요. Receiver가 뭔데 어느 쪽을 따를까요?
시험을 통해receiver는 첫 번째 조항을 따랐는데 함수 전참이 아니라 코드를 올렸습니다.
type IObject interface {
PrintValue()
}
type Object struct {
Value int
}
func (obj Object) PrintValue() { // : receiver
fmt.Println(obj.Value)
}
func main() {
var obj = Object{Value: 5}
var iObj1 IObject = obj // Object IObjedct
iObj1.PrintValue()
var iObj2 IObject = &obj // : Object IObject,
iObj2.PrintValue()
}
신기한 점: Object의 바늘도 IObject일 수 있습니다. 첫 번째 규칙을 따르기 때문에 Object 바늘 호출 방법인 PrintValue도 값을 얻는 조작부호를 사용하지만, 이 값을 부여할 때 바늘이 값을 부여하는 것이지 대상이 값을 부여하는 것이 아닙니다.
그래서 우리는 대상receiver의 방식으로 하나의 인터페이스를 실현하면 이 대상의 변수와 대상 바늘의 변수는 모두 이 인터페이스에 값을 부여할 수 있다고 말할 수 있다.
그러나receiver가 명확한 대상의 바늘이라면 대상의 바늘이 인터페이스에 값을 부여하는 것만 말할 수 있고 대상이 인터페이스에 값을 부여하는 것은 말할 수 없다
type IObject interface {
PrintValue()
}
type Object struct {
Value int
}
func (obj *Object) PrintValue() { // receiver
fmt.Println(obj.Value)
}
func main() {
var obj = Object{Value: 5}
var iObj1 IObject = obj //
iObj1.PrintValue()
var iObj2 IObject = &obj
iObj2.PrintValue()
}
다음 작은 결론:receiver는 가능한 한 바늘을 사용하고 인터페이스에 값을 부여할 때도 대상 바늘을 사용한다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Go Fiber 및 PlanetScale로 REST API 구축 - 4부다시 사용자 핸들러에 UpdateUser라는 새 함수를 추가합니다. 업데이트 사용자를 main.go에 등록 이제 응용 프로그램을 다시 실행하십시오. 이전에 생성한 사용자를 업데이트합니다. 응답 사용자가 존재하지 않을...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.