mirror of
https://gitee.com/shikong-sk/golang-study
synced 2025-02-22 23:12:15 +08:00
docs: 结构体、值接收者、构造函数
This commit is contained in:
parent
78decca578
commit
2444f78870
26
base/struct/constructor/main.go
Normal file
26
base/struct/constructor/main.go
Normal file
@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
age int
|
||||
}
|
||||
|
||||
// 构造函数 约定成俗 使用 New 开头
|
||||
// 返回结构体 因结构体为值类型 赋值的时候都是 拷贝 内存开销大
|
||||
// 返回结构体指针 当结构体比较大时 使用结构体指针 减少内存开销
|
||||
|
||||
func NewPerson(name string, age int) *Person {
|
||||
return &Person{
|
||||
name,
|
||||
age,
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
p1 := NewPerson("张三", 20)
|
||||
p2 := NewPerson("李四", 18)
|
||||
fmt.Printf("%T %#v\n", p1, p1)
|
||||
fmt.Printf("%T %#v\n", p2, p2)
|
||||
}
|
92
base/struct/main.go
Normal file
92
base/struct/main.go
Normal file
@ -0,0 +1,92 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 结构体
|
||||
// Golang 中 通过 struct 实现面向对象
|
||||
// 结构体 是 值类型
|
||||
|
||||
type Person struct {
|
||||
Age int
|
||||
Name string
|
||||
Gender string
|
||||
Hobby []string
|
||||
}
|
||||
|
||||
// golang 中 函数参数都是副本
|
||||
func change(p Person) {
|
||||
// 修改 的是 副本的 Gender
|
||||
p.Gender = "女"
|
||||
}
|
||||
|
||||
func change2(p *Person) {
|
||||
// 根据内存地址 找到 原变量 并修改
|
||||
// (*p).Gender = "女"
|
||||
|
||||
// 语法糖 自动根据指针找到变量
|
||||
p.Gender = "女"
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 声明一个 person 类型的变量
|
||||
var p1 Person
|
||||
// 通过字段赋值
|
||||
p1.Name = "于谦"
|
||||
p1.Age = time.Now().Year() - 1969
|
||||
p1.Gender = "男"
|
||||
p1.Hobby = []string{"抽烟", "喝酒", "烫头"}
|
||||
// 访问 Name 字段
|
||||
fmt.Println(p1.Name)
|
||||
fmt.Printf("type: %T value: %#v\n", p1, p1)
|
||||
|
||||
// 匿名结构体 一般用于临时场景
|
||||
var s struct {
|
||||
name string
|
||||
age int
|
||||
}
|
||||
|
||||
s.name = "s"
|
||||
s.age = 100
|
||||
fmt.Printf("type: %T value: %#v\n", s, s)
|
||||
|
||||
fmt.Println("=========================================================")
|
||||
|
||||
change(p1)
|
||||
fmt.Printf("type: %T value: %#v\n", p1, p1)
|
||||
|
||||
change2(&p1)
|
||||
fmt.Printf("type: %T value: %#v\n", p1, p1)
|
||||
|
||||
fmt.Println("=========================================================")
|
||||
|
||||
var p2 = new(Person)
|
||||
(*p2).Name = "person2"
|
||||
p2.Age = 10086
|
||||
fmt.Printf("type: %T value: %#v\n", p2, p2)
|
||||
fmt.Printf("内存地址: %p\n", p2)
|
||||
fmt.Printf("p2 的 内存地址: %p\n", &p2)
|
||||
|
||||
fmt.Println("=========================================================")
|
||||
|
||||
// 声明并初始化 结构体
|
||||
var p3 = Person{Name: "张三", Gender: "男"}
|
||||
fmt.Printf("type: %T value: %#v\n", p3, p3)
|
||||
|
||||
// 使用值列表的形式初始化 结构体
|
||||
// 值的 顺序 要和 结构体定义的 字段顺序 一致
|
||||
var p4 = Person{20, "李四", "男", []string{}}
|
||||
fmt.Printf("type: %T value: %#v\n", p4, p4)
|
||||
|
||||
fmt.Println("=========================================================")
|
||||
// 声明并初始化 结构体 指针 (常用)
|
||||
var p5 = &Person{Name: "王五", Gender: "男"}
|
||||
fmt.Printf("type: %T value: %#v\n", p5, p5)
|
||||
|
||||
// 使用值列表的形式初始化 结构体指针
|
||||
// 值的 顺序 要和 结构体定义的 字段顺序 一致
|
||||
var p6 = &Person{20, "赵六", "男", []string{}}
|
||||
fmt.Printf("type: %T value: %#v\n", p6, p6)
|
||||
}
|
23
base/struct/memory/main.go
Normal file
23
base/struct/memory/main.go
Normal file
@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// 结构体占用一块连续的内存空间
|
||||
|
||||
type memory struct {
|
||||
a int8 // 8bit => 1byte
|
||||
b int8
|
||||
c int64 // 连续的类型不同时 golang 会进行内存对齐 便于快速寻址
|
||||
}
|
||||
|
||||
func main() {
|
||||
m := memory{
|
||||
a: 10,
|
||||
b: 20,
|
||||
c: 30,
|
||||
}
|
||||
|
||||
fmt.Printf("%T\t%p\n", m.a, &m.a)
|
||||
fmt.Printf("%T\t%p\n", m.b, &m.b)
|
||||
fmt.Printf("%T\t%p\n", m.c, &m.c)
|
||||
}
|
63
base/struct/receiver/main.go
Normal file
63
base/struct/receiver/main.go
Normal file
@ -0,0 +1,63 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// golang 中 如果
|
||||
// 标识符 首字母为大写 则对外部包可见(类似 java 中 的 public)
|
||||
// 反之不可见(类似 java 中的 private)
|
||||
|
||||
// Person 人
|
||||
type Person struct {
|
||||
name string
|
||||
age int
|
||||
}
|
||||
|
||||
// 作用于 特定类型 的 函数
|
||||
// 接收者 表示的是 特定的类型变量, 常用类型首字母小写表示 不建议使用 this 或 self
|
||||
// func (接收者变量 接收者类型) 方法名(参数...) (返回值...) { ... }
|
||||
|
||||
func (p Person) Say() {
|
||||
fmt.Printf("%s: My name is %s, %d years old\n", p.name, p.name, p.age)
|
||||
}
|
||||
|
||||
// AddAge
|
||||
// 值接收者 传递的是 拷贝 的 值对象
|
||||
func (p Person) AddAge() {
|
||||
p.age++
|
||||
}
|
||||
|
||||
// AddAge2
|
||||
// 指针接收者 传递的是 对象 的 内存地址
|
||||
// 使用场景:
|
||||
// 需要修改接收者中的值
|
||||
// 接收者是拷贝代价比较大的大对象
|
||||
// 保证一致性, 如果某个方法使用了指针接收者 那么其他的方法也应该使用指针接收者
|
||||
func (p *Person) AddAge2() {
|
||||
// 原始写法
|
||||
//(*p).age++
|
||||
|
||||
// 语法糖
|
||||
p.age++
|
||||
}
|
||||
|
||||
func NewPerson(name string, age int) *Person {
|
||||
return &Person{
|
||||
name,
|
||||
age,
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
p1 := NewPerson("张三", 20)
|
||||
p1.Say()
|
||||
|
||||
fmt.Println("=========================================================")
|
||||
|
||||
p1.AddAge()
|
||||
p1.Say()
|
||||
|
||||
fmt.Println("=========================================================")
|
||||
|
||||
p1.AddAge2()
|
||||
p1.Say()
|
||||
}
|
Loading…
Reference in New Issue
Block a user