美文网首页Golang进阶
go防止接口被无意间实现

go防止接口被无意间实现

作者: qishuai | 来源:发表于2021-12-09 14:17 被阅读0次

go语言接口的独特之处在于它是满足隐式实现的鸭子模式,如果走起路来像鸭子,叫声也像鸭子,那么就会被认为是鸭子。
在go语言实现某个接口,并不需要显式声明,只要实现了接口声明的方法集合,就自动实现了该接口。但如果我们并不想让外部的包去实现我们的接口,只是作为了一种类型数据供调用端使用;或者我们想刻意的区分某一种类型和已经存在的某种具有相同函数集合的类型,因此需要对方法集合做一定的修改。

runtime包里面就有类似需求,将runtime.Error和builtin error进行区分

// The Error interface identifies a run time error.
type Error interface {
    error

    // RuntimeError is a no-op function but
    // serves to distinguish types that are run time
    // errors from ordinary errors: a type is a
    // run time error if it has a RuntimeError method.
    RuntimeError()
}

testing.TB也有类似设计:

// TB is the interface common to T and B.
type TB interface {
    Cleanup(func())
    Error(args ...interface{})
    Errorf(format string, args ...interface{})
    Fail()
    FailNow()
    Failed() bool
    Fatal(args ...interface{})
    Fatalf(format string, args ...interface{})
    Helper()
    Log(args ...interface{})
    Logf(format string, args ...interface{})
    Name() string
    Setenv(key, value string)
    Skip(args ...interface{})
    SkipNow()
    Skipf(format string, args ...interface{})
    Skipped() bool
    TempDir() string

    // A private method to prevent users implementing the
    // interface and so future additions to it will not
    // violate Go 1 compatibility.
    private()
}

上面的两种方式,主要让大家知道为什么会有这些特殊的场景,看到类似代码能够知道他的意图。
下面我们举一个例子,比如一个包中定义了一个接口,接口里面包含了一个私有方法(函数首字母小写)

package packagea

type MyStringer interface {
    String() string

    private()
}

我们我们想在另一个包中实现这个接口,代码如下:

package main

import (
    "github.com/qshuai/packagea"
)

type User struct {}

func (u *User) Error() string {
    return "error interface"
}

func (u *User) String() string {
    return "hello world"
}


func (u *User) private() {
    panic("implement me")
}

func main() {
    var _ error = (*User)(nil)
    var _ packagea.MyStringer = (*User)(nil)  // 这里会报错:cannot use (*User)(nil) (type *User) as type packagea.MyStringer in assignment:
        *User does not implement packagea.MyStringer (missing packagea.private method)
                have private()
                want packagea.private()

}

不过我们通过下面的方式变相实现上面定义的接口:

package main

import (
    "fmt"

    "github.com/qshuai/test/packagea"
)

type User struct {
    packagea.MyStringer
}

func (u *User) Error() string {
    return "error interface"
}

func (u *User) String() string {
    return "hello world"
}

//func (u *User) private() {
//  panic("implement me")
//}

func main() {
    var _ error = (*User)(nil)
    var _ packagea.MyStringer = (*User)(nil)

    var pi packagea.MyStringer = (*User)(nil)
    fmt.Println(pi.String())
}

相关文章

  • go防止接口被无意间实现

    go语言接口的独特之处在于它是满足隐式实现的鸭子模式,如果走起路来像鸭子,叫声也像鸭子,那么就会被认为是鸭子。在g...

  • Golang学习笔记-接口和错误

    接口 Go接口定义了方法后,其它类型只要实现了这些方法就是实现了接口。Go语言中接口类型的独特之处在于它是满足隐式...

  • golang-接口

    Go语言规定,只要实现了接口里面的方法,就是该接口的实现类 定义一个接口 接口实现1 接口实现 2 main方法

  • go接口与反射

    go语言的interface是个很松散的概念,类型不必明确声明实现了接口,go语言通过内部维护一个实现此接口方法的...

  • 28. 多态

    28. 多态 Go 通过[接口]来实现多态。我们已经讨论过,在 Go 语言中,我们是隐式地实现接口。一个类型如果定...

  • Go与c++混合编程

    利用cgo实现go调用c/c++的接口

  • 【Golang 基础】Go 语言的接口

    Go 语言中的接口   Go 语言中的接口就是方法签名的集合,接口只有声明,没有实现,没有数据字段。 只要某个类型...

  • 32. Readers读取数据流

    go语言的 io 包指定了 io.Reader 接口。go语言标准库包含了这个接口的许多实现,包括文件、网络连接、...

  • Go语言之Interface(二)

    使用指针接收器和值接收器实现接口 实现多个接口 接口嵌套 在Go语言中没有继承的概念,但是通过组合可以实现继承的效...

  • Go基础编程---面向对象

    面向对象 Go中没有发封装、继承、多态,但是可以通过方法、匿名字段、接口实现,Go中偏向于面向接口编程 匿名字段(...

网友评论

    本文标题:go防止接口被无意间实现

    本文链接:https://www.haomeiwen.com/subject/sldffrtx.html