在 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. webkit简介

    WebKit是一款开源的浏览器引擎,主要用于渲染HTML网页和执行JavaScript代码.WebKit起源于苹果公司,最初是为了开发Safari浏览器而创建的.现在,它已经成为许多浏览器(如苹果的S ...

  2. 谷歌浏览器新功能 Copy Declaration

    不知道最近大家有没有发现,从谷歌浏览器开发者工具复制 Css 代码到 Vs Code,粘贴之后 Css 代码错乱了.昨天在复制样式代码的时候,突然发现复制的 Css 代码粘贴之后就错乱了.具体表现如下 ...

  3. mac版本vscode窗口崩溃crashed

    1.截图 出现时机 当安装依赖的时候大概率会出现,甚至安装一次依赖会出现几次 解决 具体原因未知 重新启动电脑以及退出软件都不能解决 去官网重新下载,重新安装问题解决

  4. var ,let和const三者之间的区别

    var 声明变量可以被修改,可以被重复声明.有变量提升(写的位置和使用时候的位置不一样). let声明变量可以被修改,,但不能重复声明.如文件中有一个let a = 0;后面就不能在定义let a=* ...

  5. 对接HiveMetaStore,拥抱开源大数据

    本文分享自华为云社区<对接HiveMetaStore,拥抱开源大数据>,作者:睡觉是大事. 1. 前言 适用版本:9.1.0及以上 在大数据融合分析时代,面对海量的数据以及各种复杂的查询, ...

  6. Vite + React 组件开发实践

    简介: 毫不夸张的说,Vite 给前端带来的绝对是一次革命性的变化.或者也可以说是 Vite 背后整合的 esbuild . Browser es modules.HMR.Pre-Bundling 等 ...

  7. dotnet 修复 GitHub Action 构建过程提示 NETSDK1127 错误

    本文告诉大家,如何修复 GitHub Action 构建过程提示 error NETSDK1127: The targeting pack Microsoft.WindowsDesktop.App.W ...

  8. dotnet C# 如果在构造函数抛出异常 是否可以拿到对象赋值的变量

    如果使用某个变量去获取某个类型的对象创建,但是在这个类型的构造函数调用时抛出异常,请问此变量是否可以拿到对应的对象 如下面代码 private void F1() { Foo foo = null; ...

  9. 4.prometheus监控--监控linux服务器

    一.监控linux服务器 1.1 二进制安装 # 客户端操作wget https://github.com/prometheus/node_exporter/releases/download/v1. ...

  10. SpringBoot实现WebSocket发送接收消息 + Vue实现SocketJs接收发送消息

    SpringBoot实现WebSocket发送接收消息 + Vue实现SocketJs接收发送消息 参考: 1.https://www.mchweb.net/index.php/dev/887.htm ...