在 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 reads data from the connection.
// Read can be made to time out and return an error after a fixed
// time limit; see SetDeadline and SetReadDeadline.
Read(b []byte) (n int, err error) // Write writes data to the connection.
// Write can be made to time out and return an error after a fixed
// time limit; see SetDeadline and SetWriteDeadline.
Write(b []byte) (n int, err error) // Close closes the connection.
// Any blocked Read or Write operations will be unblocked and return errors.
Close() error // LocalAddr returns the local network address, if known.
LocalAddr() Addr // RemoteAddr returns the remote network address, if known.
RemoteAddr() Addr // SetDeadline sets the read and write deadlines associated
// with the connection. It is equivalent to calling both
// SetReadDeadline and SetWriteDeadline.
//
// A deadline is an absolute time after which I/O operations
// fail instead of blocking. The deadline applies to all future
// and pending I/O, not just the immediately following call to
// Read or Write. After a deadline has been exceeded, the
// connection can be refreshed by setting a deadline in the future.
//
// If the deadline is exceeded a call to Read or Write or to other
// I/O methods will return an error that wraps os.ErrDeadlineExceeded.
// This can be tested using errors.Is(err, os.ErrDeadlineExceeded).
// The error's Timeout method will return true, but note that there
// are other possible errors for which the Timeout method will
// return true even if the deadline has not been exceeded.
//
// An idle timeout can be implemented by repeatedly extending
// the deadline after successful Read or Write calls.
//
// A zero value for t means I/O operations will not time out.
SetDeadline(t time.Time) error // SetReadDeadline sets the deadline for future Read calls
// and any currently-blocked Read call.
// A zero value for t means Read will not time out.
SetReadDeadline(t time.Time) error // SetWriteDeadline sets the deadline for future Write calls
// and any currently-blocked Write call.
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
// A zero value for t means Write will not time out.
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. // Read implements the Conn Read method.
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
} // Write implements the Conn Write method.
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
} // Close closes the connection.
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
} // LocalAddr returns the local network address.
// The Addr returned is shared by all invocations of LocalAddr, so
// do not modify it.
func (c *conn) LocalAddr() Addr {
if !c.ok() {
return nil
}
return c.fd.laddr
} // RemoteAddr returns the remote network address.
// The Addr returned is shared by all invocations of RemoteAddr, so
// do not modify it.
func (c *conn) RemoteAddr() Addr {
if !c.ok() {
return nil
}
return c.fd.raddr
} // SetDeadline implements the Conn SetDeadline method.
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
} // SetReadDeadline implements the Conn SetReadDeadline method.
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
} // SetWriteDeadline implements the Conn SetWriteDeadline method.
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
} // SetReadBuffer sets the size of the operating system's
// receive buffer associated with the connection.
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
} // SetWriteBuffer sets the size of the operating system's
// transmit buffer associated with the connection.
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
} // File returns a copy of the underlying [os.File].
// It is the caller's responsibility to close f when finished.
// Closing c does not affect f, and closing f does not affect c.
//
// The returned os.File's file descriptor is different from the connection's.
// Attempting to change properties of the original using this duplicate
// may or may not have the desired effect.
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 添加方法的区别的更多相关文章

  1. Golang 函数以及函数和方法的区别

    在接触到go之前,我认为函数和方法只是同一个东西的两个名字而已(在我熟悉的c/c++,python,java中没有明显的区别),但是在golang中者完全是两个不同的东西.官方的解释是,方法是包含了接 ...

  2. golang中接口interface和struct结构类的分析

    再golang中,我们要充分理解interface和struct这两种数据类型.为此,我们需要优先理解type的作用. type是golang语言中定义数据类型的唯一关键字.对于type中的匿名成员和 ...

  3. golang 学习笔记 -- struct interface的使用

    一个 interface 类型定义了一个方法集做接口. 区分goalng的方法和函数 func go() { fmt.Println('go to home') } 这是函数 type car str ...

  4. Cesium 中两种添加 model 方法的区别

    概述 Cesium 中包含两种添加 model 的方法,分别为: 通过 viewer.entities.add() 函数添加 通过 viewer.scene.primitives.add() 函数添加 ...

  5. golang将interface{}转换为struct

    项目中需要用到golang的队列,container/list,需要放入的元素是struct,但是因为golang中list的设计,从list中取出时的类型为interface{},所以需要想办法把i ...

  6. golang 如何验证struct字段的数据格式

    本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/125 假设我们有如下结构体: type User struct ...

  7. C#中struct和class的区别详解

    本文详细分析了C#中struct和class的区别,对于C#初学者来说是有必要加以了解并掌握的. 简单来说,struct是值类型,创建一个struct类型的实例被分配在栈上.class是引用类型,创建 ...

  8. golang学习笔记---函数、方法和接口

    函数:对应操作序列,是程序的基本组成元素. 函数有具名和匿名之分:具名函数一般对应于包级的函数,是匿名函数的一种特例,当匿名函数引用了外部作用域中的变量时就成了闭包函数,闭包函数是函数式编程语言的核心 ...

  9. C#中struct和class的区别详解 (转载)

    本文详细分析了C#中struct和class的区别,对于C#初学者来说是有必要加以了解并掌握的. 简单来说,struct是值类型,创建一个struct类型的实例被分配在栈上.class是引用类型,创建 ...

  10. 『GoLang』结构体与方法

    结构体 结构体类型 Go 通过结构体的形式支持用户自定义类型,或者叫定制类型. Go 语言结构体是实现自定义类型的一种重要数据类型. 结构体是复合类型(composite types),它由一系列属性 ...

随机推荐

  1. SQLite总结

    废话不多说: 优点,高并发读快速度读取超越所有主流大中型数据库 缺点,缺少同步机制,读写不能同时,且同时只能有一个写入线程 用途,硬盘式缓存 另附一SQLite工具类: import java.io. ...

  2. 顺通鞋业MES生产工单管理系统软件

    顺通鞋业MES管理系统的"生产执行"是办公室和车间信息交互的枢纽,是一款针对大型鞋业生产企业开发的可配置化智能制造管理系统.工人可以通过车间终端(如安装在机器旁的固定工业触摸屏或移 ...

  3. 国内chatGPT中文版网站有哪些?国内人工智能百花齐放!该如何选择?

    人工智能技术在中国的快速发展和普及,使得国内的人工智能产业日益壮大.在这些领域中,自然语言处理技术和聊天机器人已经取得了显著的进展.ChatGPT作为一种基于深度学习的聊天机器人模型,在国内得到了广泛 ...

  4. vscode使用ES6装饰器器语法

    1. react项目 配置 package.json 需要安装 npm i @babel/plugin-proposal-decorators 可能需要重启项目 { "babel" ...

  5. Serverless 架构下的 AI 应用开发:入门、实战与性能优化

    简介: 本章通过对 Serverless 架构概念的探索,对 Serverless 架构的优势与价值.挑战与困境进行分析,以及 Serverless 架构应用场景的分享,为读者介绍 Serverles ...

  6. 码住!Flink Contributor 速成指南

    简介: 不管初衷是什么,Flink 都非常欢迎大家一起建设和完善社区.在开始具体的贡献步骤之前,我们先简要介绍一下参与贡献的几种途径,以及 Clarify 关于开源贡献的一些固有印象. 作者:伍翀(云 ...

  7. 智能数据构建与管理平台Dataphin的前世今生:缘起

    简介: 阿里巴巴提出的OneData方法论帮助企业捋清了数据全生命周期的管理思路,更将其植入到产品Dataphin(智能数据构建与管理)中,通过阿里云为企业提供服务. Dataphin 智能数据构建与 ...

  8. [GPT] ./ssh/known_hosts 是什么

      ~/.ssh/known_hosts 是一个SSH客户端用来存储已知的远程主机的公钥的文件,这些公钥用于验证连接到远程主机时它们是否为真实可信的主机. 当你首次通过SSH连接到一个新的远程主机时, ...

  9. [Gin] gin-jwt 中间件的请求流程与使用思路

    gin-jwt 中间件是对 jwt-go 的封装以适应 gin 框架.gin-jwt 对不同的请求流程有不同的 handler: 登录请求流程 是用 LoginHandler. 需要 jwt 令牌的后 ...

  10. k8s问题解决

    问题1: 问题描述:k8s中Terminating状态pod不能删除 [root@master ~]# kubectl get pods -n ms NAME READY STATUS RESTART ...