1. Go的“轻量级面向对象”
Go没有传统的类和继承,而是通过结构体(struct)和接口(interface)实现面向对象的效果。
2. 指针
基本用法
1 2 3 4 5 6
| var num int = 42 var p *int = &num fmt.Println(*p)
*p = 100 fmt.Println(num)
|
注意:
- 安全限制:Go指针不支持算术运算(如
p++
),避免C语言的内存错误。
- 用途:函数传参避免拷贝大结构体、修改外部变量。
与C指针的对比
特性 |
Go指针 |
C指针 |
算术运算 |
❌ 不支持 |
✔️ 支持 |
空指针安全 |
运行时检查(panic) |
段错误(Segfault) |
默认值 |
nil |
未定义 |
3. 结构体(struct):
定义与初始化
1 2 3 4 5 6 7 8 9 10
| type Person struct { Name string Age int skills []string }
p1 := Person{"Alice", 25, []string{"Go", "Python"}} p2 := Person{Name: "Bob", Age: 30} p3 := new(Person)
|
方法接收者
go语言没有类,没用类函数,但是可以通过给函数添加一个方法接受者,让其达到类似于类函数的效果,语法如下:
func (结构体) 函数名(参数)
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| func (p Person) SayHello() { fmt.Printf("Hi, I'm %s\n", p.Name) }
func (p *Person) AddSkill(skill string) { p.skills = append(p.skills, skill) }
func (Person) SayHello() { fmt.Println("Hello") }
p := Person{Name: "jeanhua"} p.SayHello() p.AddSkill("C#")
|
注意:
- 需要修改原结构体时用指针接收者。
- 大结构体或高频调用优先用指针(减少拷贝开销)。
4. 接口(interface)
隐式实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| type Speaker interface { Speak() string }
type Dog struct{}
func (d Dog) Speak() string { return "Woof!" }
func greet(s Speaker) { fmt.Println(s.Speak()) }
func main() { greet(Dog{}) var dog Speaker = Dog{} fmt.Println(dog.Speak()) }
|
注意:
- 无需
implements
关键字:只要方法匹配即视为实现接口。
- 接口变量存储
(值, 类型)
对:可动态持有任意实现者。
go的接口实现只需要实现该结构体作为方法接收者来实现某接口的所有同名函数,实现接口后可将该结构体赋值给接口
空接口与类型断言
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| var any interface{} = "hello"
if s, ok := any.(string); ok { fmt.Println(s) }
switch v := any.(type) { case int: fmt.Println("int:", v) case string: fmt.Println("string:", v) default: fmt.Println("unknown") }
|
5. 实战:文件系统接口设计
需求:实现一个通用文件存储接口
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| type FileStorage interface { Read(path string) ([]byte, error) Write(path string, data []byte) error }
type LocalStorage struct{}
func (ls LocalStorage) Read(path string) ([]byte, error) { return os.ReadFile(path) }
func (ls LocalStorage) Write(path string, data []byte) error { return os.WriteFile(path, data, 0644) }
func SaveConfig(storage FileStorage, path string, data []byte) error { return storage.Write(path, data) }
|
6. 更多
结构体字段后面可以添加标签,通过反射可以获取标签内容
1 2 3 4
| type User struct { Name string `json:"name" db:"user_name"` }
|
接口零值
1 2 3 4
| var s Speaker if s == nil { fmt.Println("未赋值") }
|