2.12. 补充注意事项 10 最好不要在结构体中定义 `pointer receiver` 的方法
g g study,d d up!
补充注意事项 10
最好不要在结构体中定义 pointer receiver
的方法
10. 最好不要在结构体中定义 pointer receiver
的方法,以避免使用者对结构体进行无意中的修改。如果需要对结构体进行修改,可以使用 value receiver
的方法。
在 Go 中,方法可以是值接收器或指针接收器。使用值接收器时,方法接收器是值的副本,因此方法对值的修改不会影响原始值。使用指针接收器时,方法接收器是指针,因此方法对指针指向的值进行修改,将影响原始值。
如果一个结构体类型的方法使用指针接收器,它允许在调用该方法时修改结构体实例的字段。如果使用值接收器,方法将无法修改结构体实例的字段,因为它们只是值的副本。因此,在设计结构体类型时,应该根据使用情况选择正确的接收器类型,以确保结构体实例的正确性和安全性。
如果结构体类型中的方法使用指针接收器,并且使用者对该结构体实例的指针进行了修改,那么这可能会导致未知的副作用和竞态条件。因此,最好不要在结构体类型中定义指针接收器的方法,除非有充分的理由需要这样做,并且应该确保使用者了解这些方法的影响和安全性。
相反,如果结构体类型中的方法使用值接收器,使用者可以安全地复制结构体实例,而不必担心在修改原始实例时发生意外的更改。因此,在结构体类型中定义值接收器的方法是一个更好的选择,以避免对结构体实例的无意中修改。
下面是一个使用值接收器的例子,用于在结构体中存储和获取学生的成绩信息:
package main
import "fmt"
type Student struct {
Name string
Scores []int
Avg float64
}
func (s Student) AddScore(score int) {
s.Scores = append(s.Scores, score)
}
func (s Student) CalculateAverage() {
sum := 0
for _, score := range s.Scores {
sum += score
}
s.Avg = float64(sum) / float64(len(s.Scores))
}
func (s *Student) CalculateAveragePoint() {
sum := 0
for _, score := range s.Scores {
sum += score
}
s.Avg = float64(sum) / float64(len(s.Scores))
}
func main() {
student := Student{Name: "Tom", Scores: []int{80, 90, 85}}
student.AddScore(95)
student.CalculateAverage()
fmt.Println(student.Name, student.Scores, student.Avg)
fmt.Println("--------------------------teacher------------------")
// 传入指针
teacher := Student{Name: "Tom", Scores: []int{80, 90, 85}}
teacher.CalculateAveragePoint()
fmt.Println(teacher.Name, teacher.Scores, teacher.Avg)
}
在上面的例子中,AddScore
和 CalculateAverage
方法都使用值接收器。在 AddScore
方法中,我们试图向 Scores
切片中添加一个新的成绩。但是,在这个方法中,我们实际上并没有修改原始结构体中的 Scores
字段,因为 s
是值的副本,而不是原始结构体的引用。这意味着我们向 s.Scores
添加的新分数仅影响值接收器 s
,而不是原始结构体中的 Scores
字段。因此,在主函数中输出的 Scores
字段仍然是 []int{80, 90, 85}
。
在 CalculateAverage
方法中,我们试图计算学生的平均分数。但是,与 AddScore
方法一样,我们无法修改原始结构体中的 Avg
字段。因此,在主函数中输出的 Avg
字段仍然是 0.0
。
因此,在这种情况下,使用值接收器的方法不能修改原始结构体的字段,我们应该使用指针接收器的方法,以便我们能够修改结构体的字段。
CalculateAveragePoint
就是使用指针。
输出结果如下:
λ go run test.go
Tom [80 90 85] 0
--------------------------teacher------------------
Tom [80 90 85] 85
欢迎关注公众号上海php自学中心,一起交流。