golang interface 和 struct 添加方法的区别

golang,interface,struct · 浏览次数 : 0

小编点评

在Go语言中,结构体(struct)和接口(interface)都可以关联方法,但它们的实现方式不同。结构体通过定义一个指向该结构体类型的指针作为接收者的函数来为结构体“添加”方法;而接口则通过定义一组方法签名来实现。以下是详细的解释和示例: 1. 结构体添加方法: 结构体本身不直接包含方法,但可以通过定义一个指向该结构体类型的指针作为接收者的函数来为结构体“添加”方法。示例中提到了一个名为`MyStruct`的结构体,其中定义了一个名为`MyMethod`的方法,该方法关联到了`MyStruct`结构体。通过指针接收者`*MyStruct`,我们可以将该方法绑定到结构体上。 ```go type MyStruct struct { // fields } func (s *MyStruct) MyMethod() { // method body } ``` 2. 接口添加方法: 接口并不直接定义方法,而是定义了一组方法签名。当一个结构体实现了接口所要求的所有方法时,我们说这个结构体实现了该接口。示例中提到了一个名为`MyInterface`的接口,其中定义了一个名为`MyMethod`的方法签名。一个结构体实现了`MyInterface`接口,意味着它包含了`MyMethod`方法签名定义的所有方法。 ```go type MyInterface interface { MyMethod() } ``` 为了使结构体实现接口,只需确保该结构体实现了`MyMethod`方法签名。 总的来说,结构体通过定义方法接收者来关联方法,而接口通过定义方法签名来间接要求实现它的类型具备相应的方法。这种实现方式使得结构体和接口能够在运行时灵活地扩展功能。

正文

 

在 Go 语言中,struct 和 interface 都可以关联方法,但它们的方式不同:

1. struct 添加方法:
  结构体(struct)本身不直接包含方法,但可以通过定义一个指向该结构体类型的指针作为接收者的函数来为结构体“添加”方法。

type MyStruct struct {
    // fields
}

func (s *MyStruct) MyMethod() {
    // method body
}

这里的 MyMethod 是一个与 MyStruct 关联的方法,通过指针接收者 *MyStruct 实现。


2. interface 添加方法:

接口(interface)并不直接定义方法,而是定义了一组方法签名。当一个结构体实现了接口所要求的所有方法时,我们说这个结构体实现了该接口。

 

type MyInterface interface {
    MyMethod()
}

// 不需要显式声明实现,只要MyStruct有匹配的方法签名即可
func (s *MyStruct) MyMethod() {
    // method body
}

在上面的例子中,MyStruct 通过其 MyMethod 实现了 MyInterface,无需任何额外的代码。


总结来说,结构体通过定义"方法接收者"来关联方法,而接口通过定义"一组方法签名"来间接要求实现它的类型具备相应的方法


实例见: $GOROOT/src/net/net.go 局部

Conn 接口表示一个通用的面向流的网络连接,并定义了读取、写入、关闭以及为 I/O 操作设置截止时间的多种方法。

可以在多个goroutine中同时调用其方法。

  Read 方法从连接中读取数据到给定的字节片,并返回读取的字节数和遇到的任何错误。
  Write 方法将给定字节片中的数据写入连接,并返回写入的字节数和遇到的任何错误。
  Close 方法关闭连接并返回关闭过程中发生的任何错误。
  LocalAddr 方法返回连接的本地网络地址(如果已知)。
  RemoteAddr 方法返回连接的远程网络地址(如果已知)。
  SetDeadline 方法为连接设置读取和写入的截止时间。如果超过截止时间,后续的 I/O 操作会失败并返回错误。
  SetReadDeadline 方法为未来的 Read 调用及当前阻塞的 Read 调用设置截止时间。
  SetWriteDeadline 方法为未来的 Write 调用及当前阻塞的 Write 调用设置截止时间。即使写入超时,也可能返回 n > 0,表明部分数据已成功写入。

conn 结构体是 Conn 接口的一个具体实现,它使用 netFD 对象来表示底层的文件描述符。

// Conn is a generic stream-oriented network connection.
//
// Multiple goroutines may invoke methods on a Conn simultaneously.
type Conn interface {
    Read(b []byte) (n int, err error)
    Write(b []byte) (n int, err error)
    Close() error
    LocalAddr() Addr
    RemoteAddr() Addr
    SetDeadline(t time.Time) error
    SetReadDeadline(t time.Time) error
    SetWriteDeadline(t time.Time) error
}

type conn struct {
    fd *netFD
}

func (c *conn) ok() bool { return c != nil && c.fd != nil }

// Implementation of the Conn interface.

func (c *conn) Read(b []byte) (int, error) {
    if !c.ok() {
        return 0, syscall.EINVAL
    }
    n, err := c.fd.Read(b)
    if err != nil && err != io.EOF {
        err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
    }
    return n, err
}

func (c *conn) Write(b []byte) (int, error) {
    if !c.ok() {
        return 0, syscall.EINVAL
    }
    n, err := c.fd.Write(b)
    if err != nil {
        err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
    }
    return n, err
}

func (c *conn) Close() error {
    if !c.ok() {
        return syscall.EINVAL
    }
    err := c.fd.Close()
    if err != nil {
        err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
    }
    return err
}

func (c *conn) LocalAddr() Addr {
    if !c.ok() {
        return nil
    }
    return c.fd.laddr
}

func (c *conn) RemoteAddr() Addr {
    if !c.ok() {
        return nil
    }
    return c.fd.raddr
}

func (c *conn) SetDeadline(t time.Time) error {
    if !c.ok() {
        return syscall.EINVAL
    }
    if err := c.fd.SetDeadline(t); err != nil {
        return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
    }
    return nil
}

func (c *conn) SetReadDeadline(t time.Time) error {
    if !c.ok() {
        return syscall.EINVAL
    }
    if err := c.fd.SetReadDeadline(t); err != nil {
        return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
    }
    return nil
}

func (c *conn) SetWriteDeadline(t time.Time) error {
    if !c.ok() {
        return syscall.EINVAL
    }
    if err := c.fd.SetWriteDeadline(t); err != nil {
        return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
    }
    return nil
}

func (c *conn) SetReadBuffer(bytes int) error {
    if !c.ok() {
        return syscall.EINVAL
    }
    if err := setReadBuffer(c.fd, bytes); err != nil {
        return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
    }
    return nil
}

func (c *conn) SetWriteBuffer(bytes int) error {
    if !c.ok() {
        return syscall.EINVAL
    }
    if err := setWriteBuffer(c.fd, bytes); err != nil {
        return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
    }
    return nil
}

func (c *conn) File() (f *os.File, err error) {
    f, err = c.fd.dup()
    if err != nil {
        err = &OpError{Op: "file", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
    }
    return
}

  

Link:https://www.cnblogs.com/farwish/p/18236119

与golang interface 和 struct 添加方法的区别相似的内容:

golang interface 和 struct 添加方法的区别

在 Go 语言中,struct 和 interface 都可以关联方法,但它们的方式不同: 1. struct 添加方法: 结构体(struct)本身不直接包含方法,但可以通过定义一个指向该结构体类型的指针作为接收者的函数来为结构体“添加”方法。 type MyStruct struct { //

golang Context应用举例

Context本质 golang标准库里Context实际上是一个接口(即一种编程规范、 一种约定)。 type Context interface { Deadline() (deadline time.Time, ok bool) Done() <-chan struct{} Err() err

Go 语言中的异常处理简单实践 panic、recover【GO 基础】

〇、Go 中的异常处理简介 Golang 没有结构化异常,使用 panic 抛出错误,recover 捕获错误。 panic、recover 参数类型为 interface{},因此可抛出任何类型对象。 func panic(v interface{}) func recover() interfa

Golang 切片作为函数参数传递的陷阱与解答

作者:林冠宏 / 指尖下的幽灵。转载者,请: 务必标明出处。 GitHub : https://github.com/af913337456/ 出版的书籍: 《1.0-区块链DApp开发实战》 《2.0-区块链DApp开发:基于公链》 例子 切片作为函数参数传递的是值 用来误导切片作为函数参数传递的

golang 所有关键字的列表及释义归类

golang 所有关键字的列表及释义归类,截至1.18版本。 [控制结构] if : 条件语句,基于布尔表达式的值决定是否执行特定的代码块。 else、 else if : 用在 if 语句之后,当条件表达式为假时执行的代码块。 switch : 多路选择语句,根据不同的情况执行不同的代码块。 ca

golang 泛型的格式写法

Go语言中的泛型(Generics)是在 Go 1.18 版本中引入的一个重要特性,它允许你编写可重用的代码,而不需要为每种数据类型重复编写相同的逻辑。 泛型通过参数化类型(type parameters)来实现,使得函数、方法、接口和结构体可以与多种类型一起工作。 下面详细介绍Go语言中泛型的基本

Golang channel底层是如何实现的?(深度好文)

Go语言为了方便使用者,提供了简单、安全的协程数据同步和通信机制,channel。那我们知道channel底层是如何实现的吗?今天k哥就来聊聊channel的底层实现原理。同时,为了验证我们是否掌握了channel的实现原理,本文也收集了channel的高频面试题,理解了原理,面试题自然不在话下。

Golang 依赖注入设计哲学|12.6K 的依赖注入库 wire

本文从“术”层面,讲述“依赖注入”的实现,带你体会其对于整洁架构 & DDD 等设计思想的落地,起到的支撑作用。

[golang]在Gin框架中使用JWT鉴权

什么是JWT JWT,全称 JSON Web Token,是一种开放标准(RFC 7519),用于安全地在双方之间传递信息。尤其适用于身份验证和授权场景。JWT 的设计允许信息在各方之间安全地、 compactly(紧凑地)传输,因为其自身包含了所有需要的认证信息,从而减少了需要查询数据库或会话存储

golang如何使用指针灵活操作内存?unsafe包原理解析

本文将深入探讨Golang中unsafe包的功能和原理。同时,我们学习某种东西,一方面是为了实践运用,另一方面则是出于功利性面试的目的。所以,本文还会为大家介绍unsafe 包的典型应用以及高频面试题。