GoLang의 인터페이스, 포인터 등

9072 단어 GO
직접 부호:
우선, 나는 세 개의 인터페이스, 하나의 구조와 세 가지 방법을 정했다.
type DeptModeFull interface {
    Name() string
    SetName(name string)
    Relocate(building string, floor uint8)
}

type DeptModeA interface {
    Name() string
    SetName(name string)
}

type DeptModeB interface {
    Relocate(building string, floor uint8)
}

type Dept struct {
    name     string
    building string
    floor    uint8
    Key      string
}

func (self Dept) Name() string {
    return self.name
}

func (self Dept) SetName(name string) {
    self.name = name
}

func (self *Dept) Relocate(building string, floor uint8) {
    self.building = building
    self.floor = floor
}

그 후에 나는 몇 가지 테스트 코드를 썼다.
dept1 :=
    Dept{
        name:     "MySohu",
        building: "Internet",
        floor:    7}
switch v := interface{}(dept1).(type) {
case DeptModeFull:
    fmt.Printf("The dept1 is a DeptModeFull.
"
) case DeptModeB: fmt.Printf("The dept1 is a DeptModeB.
"
) case DeptModeA: fmt.Printf("The dept1 is a DeptModeA.
"
) default: fmt.Printf("The type of dept1 is %v
"
, v) } deptPtr1 := &dept1 if _, ok := interface{}(deptPtr1).(DeptModeFull); ok { fmt.Printf("The deptPtr1 is a DeptModeFull.
"
) } if _, ok := interface{}(deptPtr1).(DeptModeA); ok { fmt.Printf("The deptPtr1 is a DeptModeA.
"
) } if _, ok := interface{}(deptPtr1).(DeptModeB); ok { fmt.Printf("The deptPtr1 is a DeptModeB.
"
) }

인쇄된 내용:
The dept1 is a DeptModeA.

The deptPtr1 is a DeptModeFull.

The deptPtr1 is a DeptModeA.

The deptPtr1 is a DeptModeB.

내 질문:
왜 Dept의 실례의 바늘은 모든 세 인터페이스의 실현으로 판정되고 Dept의 실례는 DeptModeA 인터페이스의 실현일 뿐입니까?
어느 큰 소가 말씀해 주시겠어요?
대답 1:
T가 struct라고 가정하면 Go에서는 다음과 같은 몇 가지 원칙을 따릅니다.
  • T의 메소드 세트에는 T Receiver 메소드만 있습니다.
  • *T 방법집은 모든 방법(T + *T)을 포함합니다.

  • 따라서 위의 예는 dept1이 가지고 있는 방법일 것입니다: Name과 SetName
    &dept1에는 Name, SetName 및 Relocate가 있습니다.
    이게 바로 Go 안에서 디자인 방법을 쓸 때 Receiver의 장르에 신경을 써야 돼요.
    대답 2:
    이상의 고수들의 해답에 감사드리며 공식 규범 문서를 자세히 봤습니다(http://tip.golang.org/ref/spec의 관련 내용은 위의 예에 대해 제가 다시 한 번 요약해 보겠습니다(위의 몇 분이 제공한 답안이 포함되어 있습니다).
    1. 구조 Dept의 방법은 방법 수신자가 Dept인 방법만 포함한다. 즉, Name()SetName()).따라서 구조 Dept의 실례는 DeptModeA의 실현에 불과하다.2. 구조의 지침 *Dept의 방법집은 방법 수용자가 Dept*Dept인 방법, 즉 Name(), SetName()Relocate()을 포함한다.따라서 인터페이스 Dept의 실례적인 지침은 모든 세 개의 인터페이스인 DeptModeFull, DeptModeADeptModeB의 실현이다.
    그러나 나는 상술한 디자인과 원칙이 방법이 호출한 디자인과 약간 일치하지 않는다고 생각한다. 아래의 코드를 보십시오.
    dept1.Relocate("Media", 12)
    fmt.Printf("Dept: %v
    "
    , dept1) fmt.Printf("Dept name: %v
    "
    , deptPtr1.Name())

    인쇄된 내용:
    Dept: {MySohu Media 12 }

    Dept name: MySohu
    

    구조 Dept의 실례는 지침 방법을 집중적으로 사용할 수 있다는 뜻이다.
    설계가 일치하지 않는 점은 구조의 방문법집은 수신자가 지침을 주는 방법을 포함하지 않는 이상 왜 구조의 실례에서 지침을 사용하는 방법을 사용할 수 있겠는가?반대로 보면 구조의 실례가 그 인터페이스 방문법집의 방법을 사용할 수 있는 이상 왜 구조의 방법집에 이러한 방법을 직접 포함하지 못하게 합니까?
    그러나 어쨌든 이것은 제3조 규칙(공식규범의 의역)을 인용했다. 3. 구조의 실례인 x이'어디서 찾을 수 있는'것이고 &x의 방법은 방법 m을 집중적으로 포함하면 x.m()(&x).m()의 속기(단축방식)이다.
    그래서 사실
    dept1.Relocate("Media", 12)
    

    자동으로 바뀌었어?
    (&dept1).Relocate("Media", 12)
    

    공부했어.
    주소를 찾는다는 뜻은 아마도 이미 실례가 된 것일 것이다.하면, 만약, 만약...
    var deptPtr2 *Dept
    deptPtr2.Relocate("Media", 12)
    

    안돼.반대로:
    var deptPtr2 Dept
    deptPtr2.Relocate("Media", 12)
    

    할 수 있어.차이는 바로 여기에 있다.
    ========================================================================
    별례
    type Reader interface {read ()} type Writer interface {write ()}//상기 두 인터페이스의 구현 클래스 type My ReadWrite struct {}func (mrw * My ReadWrite) read () read () {fmt. Pritln ("My ReadWrite...read))}func (mrw * My ReadWrite) write ()상기 두 인터페이스 type ReadWriter interface {Reader Writer}//위의 인터페이스는 type ReadWriter V2 interface {read () write ()}//ReadWriter와 ReadWriter V2 두 인터페이스가 같은 값이므로 func interfaceTest0104 () {mrw: = My ReadWrite {mrw.read()    mrw.write()//mrw 객체는read() 방법과 write() 방법을 구현하므로 ReadWriter 및 ReadWriter V2 var rw1 ReadWriter = mrw rw1.read()    rw1.write()    fmt.Println("------")    var rw2 ReadWriterV2 = mrw    rw2.read()    rw2.write ()//동시에 ReadWriter와 ReadWriter V2 두 인터페이스 대상은 서로 rw1 = rw2 rw2 = rw2 = rw1}func main () {interfaceTest0104 ()}
    빨간색으로 표시된 두 줄은 오류를 보고할 수 있다
    main\interface.go:43:6: cannot use mrw (type MyReadWrite) as type ReadWriter in assignment:    MyReadWrite does not implement ReadWriter (read method has pointer receiver)main\interface.go:48:6: cannot use mrw (type MyReadWrite) as type ReadWriterV2 in assignment:    MyReadWrite does not implement ReadWriterV2 (read method has pointer receiver)
    ReadWriter와 ReadWriter V2의 실현은 모두 수락된 포인터 파라미터이기 때문에 *T receiver이고 mrw는 T receiver만 있고 파라미터를 포인터로 실현하는 방법이 없기 때문에 (이곳의 mrw는 어떤 방법도 실현하지 못했을 수 있습니다. mrw.read()가 성공할 수 있는 것은 위에서 언급한 세 번째 점 때문) 값을 부여할 수 없습니다.
    mrw:=&MyReadWrite {}로 변경하면 오류 없음

    좋은 웹페이지 즐겨찾기