方法 - Go 语言学习笔记

什么是方法?

Go 语言中同时有函数和方法。方法就是一个包含了接收者的函数,接收者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。

在 Go 中,(接收者)类型关联的方法不写在类型结构里面,就像类那样;耦合更加宽松;类型和方法之间的关联由接收者来建立。 方法没有和数据定义(结构体)混在一起:它们是正交的类型;表示(数据)和行为(方法)是独立的。

声明方法

语法格式如下:

func (variable_receiver_name receiver_type) function_name([parameter list]) [return_type]{
    /* 函数体*/
}
复制代码
  • variable_receiver_name 接收者必须有一个显式的名字,这个名字必须在方法中被使用。官方建议使用接收器类型名的第一个小写字母,而不是 self、this 之类的命名。例如,Socket 类型的接收器变量应该命名为 s,Connector 类型的接收器变量应该命名为 c 等。
  • receiver_type 叫做 (接收者)基本类型,这个类型必须在和方法同样的包中被声明。
  • 方法名、参数列表、返回参数:格式与函数定义一致。
package main
import (
    "fmt"  
)

// 定义结构体
type Circle struct {
    radius float64
}

func main() {
    var c1 Circle
    c1.radius = 10.00
    fmt.Println("圆的面积 = ", c1.getArea())
}

// 该 method 属于 Circle 类型对象中的方法
func (c Circle) getArea() float64 {
    // c.radius 即为 Circle 类型对象中的属性
    return 3.14 * c.radius * c.radius
}

// 执行结果为:的面积 =  314
复制代码

接收者

接收者有两种,一种是值接收者,一种是指针接收者。顾名思义,值接收者,是接收者的类型是一个值,是一个副本,方法内部无法对其真正的接收者做更改;指针接收者,接收者的类型是一个指针,是接收者的引用,对这个引用的修改之间影响真正的接收者。像上面一样定义方法,将 user 改成 *user 就是指针接收者。

调用方法

struct的方法调用

方法调用相当于普通函数调用的语法糖。Value方法的调用m.Value()等价于func Value(m M) 即把对象实例m作为函数调用的第一个实参压栈,这时m称为receiver。通过实例或实例的指针其实都可以调用所有方法,区别是复制给函数的receiver不同。

如下,通过实例m调用Value时,以及通过指针p调用Value时,receiver是m和*p,即复制的是m实例本身。因此receiver是m实例的副本,他们地址不同。通过实例m调用Pointer时,以及通过指针p调用Pointer时,复制的是都是&m和p,即复制的都是指向m的指针,返回的都是m实例的地址。

type M struct {
    a int
}
func (m M) Value() string {return fmt.Sprintf("Value: %p\n", &m)}
func (m *M) Pointer() string {return fmt.Sprintf("Pointer: %p\n", m)}
var m M
p := &m      // p is address of m 0x2101ef018
m.Value()    // value(m) return 0x2101ef028
m.Pointer()  // value(&m) return 0x2101ef018
p.Value()    // value(*p) return 0x2101ef030
p.Pointer()  // value(p) return 0x2101ef018
复制代码

方法用法

1. 基于指针对象的方法

当接受者变量本身比较大时,可以用其指针而不是对象来声明方法,这样可以节省内存空间的占用。

package main
import (
    "fmt"
    "math"
)

// 方法声明
type Point struct {
	X,Y float64
}

func (p *Point) Distance(q *Point) float64 {
	return math.Hypot(q.X - p.X, q.Y - p.Y)
}

func main() {
	p := &Point{3,5}
	fmt.Println(p.Distance(&Point{5, 6}))
}

// 执行结果为:2.23606797749979
复制代码
2. 将nil作为接收器
package main

import "fmt"

// 将nil作为接收器
type IntNode struct {
	Value int
	Next *IntNode
}

func (node *IntNode) Sum() int  {
	if node == nil {
		return 0
	}
	return node.Value + node.Next.Sum()

}

func main()  {
	node1 := IntNode{30, nil}
	node2 := IntNode{12, nil}
	node3 := IntNode{43, nil}

	node1.Next = &node2
	node2.Next = &node3

	fmt.Println(node1.Sum())
	fmt.Println(node2.Sum())

	node := &IntNode{3, nil}
	node = nil
	fmt.Println(node.Sum())
}
// 执行结果为:
// 85
// 55
// 0
复制代码
3. 通过嵌入结构体拓展类型

示例:

package main

import (
    "fmt"
)

// 基础颜色
type BasicColor struct {
    // 红、绿、蓝三种颜色分量
    R, G, B float32
}

// 完整颜色定义
type Color struct {
    // 将基本颜色作为成员
    BasicColor
    
    // 透明度
    Alpha float32
}

func main() {
    
    // 设置基本颜色分量
    var c Color
    c.R = 1
    c.G = 1
    c.B = 0
    
    // 设置透明度
    c.Alpha = 1
    
    // 显示整个结构体内容
    fmt.Printf("%+v", c)
}
复制代码

代码输出如下: {Basic:{R:1 G:1 B:0} Alpha:1}

Go语言的结构体内嵌特性:

  1. 内嵌的结构体可以直接访问其成员变量
    嵌入结构体的成员,可以通过外部结构体的实例直接访问。如果结构体有多层嵌入结构体,结构体实例访问任意一级的嵌入结构体成员时都只用给出字段名,而无须像传统结构体字段一样,通过一层层的结构体字段访问到最终的字段。例如,ins.a.b.c的访问可以简化为ins.c。
  2. 内嵌结构体的字段名是它的类型名
    内嵌结构体字段仍然可以使用详细的字段进行一层层访问,内嵌结构体的字段名就是它的类型名,代码如下:
var c Color
c.BasicColor.R = 1
c.BasicColor.G = 1
c.BasicColor.B = 0
复制代码

一个结构体只能嵌入一个同类型的成员,无须担心结构体重名和错误赋值的情况,编译器在发现可能的赋值歧义时会报错。

转载于:https://juejin.im/post/5cf623c35188256d9c232b76

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值