jee said
Go语言结构体与方法
Go语言通过结构体和方法来实现面向对象编程的特性。与传统的类不同,Go的结构体和方法是分离的,这使得代码更加灵活。
结构体定义
基本语法
type Person struct {
Name string
Age int
}
type Point struct {
X, Y float64
}结构体实例化
// 方式1:按顺序初始化
p1 := Person{"张三", 30}
// 方式2:按字段名初始化(推荐)
p2 := Person{
Name: "李四",
Age: 25,
}
// 方式3:使用new函数
p3 := new(Person)
p3.Name = "王五"
p3.Age = 35结构体标签
type User struct {
ID int `json:"id"`
Username string `json:"username" db:"user_name"`
Email string `json:"email" db:"email"`
Created time.Time `json:"created_at"`
}方法定义
Go语言的方法是带有接收者的函数。
值接收者
type Rectangle struct {
Width float64
Height float64
}
// 值接收者
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func main() {
rect := Rectangle{Width: 3, Height: 4}
fmt.Println(rect.Area()) // 12
}指针接收者
type Counter struct {
count int
}
// 指针接收者(可以修改原值)
func (c *Counter) Increment() {
c.count++
}
func (c *Counter) GetCount() int {
return c.count
}
func main() {
c := Counter{count: 0}
c.Increment()
fmt.Println(c.GetCount()) // 1
}值接收者 vs 指针接收者
type Point struct {
X, Y float64
}
// 值接收者:不修改原值
func (p Point) String() string {
return fmt.Sprintf("(%f, %f)", p.X, p.Y)
}
// 指针接收者:修改原值
func (p *Point) Move(dx, dy float64) {
p.X += dx
p.Y += dy
}结构体组合
Go语言通过组合而非继承来复用代码。
匿名嵌入
type Address struct {
City string
Country string
}
type Person struct {
Name string
Address // 匿名嵌入
}
func main() {
p := Person{
Name: "张三",
Address: Address{
City: "北京",
Country: "中国",
},
}
// 可以直接访问嵌入字段
fmt.Println(p.City) // 北京
fmt.Println(p.Country) // 中国
}方法提升
func (a Address) FullAddress() string {
return fmt.Sprintf("%s, %s", a.City, a.Country)
}
func main() {
p := Person{
Name: "张三",
Address: Address{City: "北京", Country: "中国"},
}
// 嵌入类型的方法被提升
fmt.Println(p.FullAddress()) // 北京, 中国
}命名嵌入
type Person struct {
Name string
Addr Address // 命名嵌入
}
func main() {
p := Person{
Name: "张三",
Addr: Address{City: "北京", Country: "中国"},
}
// 需要通过嵌入字段访问
fmt.Println(p.Addr.City) // 北京
}结构体比较
type Point struct {
X, Y float64
}
func main() {
p1 := Point{X: 1, Y: 2}
p2 := Point{X: 1, Y: 2}
p3 := Point{X: 1, Y: 3}
fmt.Println(p1 == p2) // true
fmt.Println(p1 == p3) // false
}结构体与JSON
序列化
type User struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
}
func main() {
user := User{
ID: 1,
Username: "zhangsan",
Email: "zhangsan@example.com",
}
data, _ := json.Marshal(user)
fmt.Println(string(data))
// {"id":1,"username":"zhangsan","email":"zhangsan@example.com"}
}反序列化
func main() {
jsonData := `{"id":1,"username":"zhangsan","email":"zhangsan@example.com"}`
var user User
json.Unmarshal([]byte(jsonData), &user)
fmt.Printf("%+v\n", user)
// {ID:1 Username:zhangsan Email:zhangsan@example.com}
}最佳实践
- 使用指针接收者:当方法需要修改结构体时
- 使用值接收者:当方法不需要修改结构体时
- 使用组合而非继承:通过嵌入实现代码复用
- 合理使用结构体标签:JSON、数据库映射等场景
- 导出字段:首字母大写的字段才能被外部包访问
总结
Go语言的结构体和方法提供了一种简洁而强大的面向对象编程方式。通过组合而非继承,Go的代码更加灵活和可维护。掌握结构体和方法的用法是Go语言开发的基础。