diff --git a/base/struct/constructor/main.go b/base/struct/constructor/main.go new file mode 100644 index 0000000..db7cd53 --- /dev/null +++ b/base/struct/constructor/main.go @@ -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) +} diff --git a/base/struct/main.go b/base/struct/main.go new file mode 100644 index 0000000..35794a4 --- /dev/null +++ b/base/struct/main.go @@ -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) +} diff --git a/base/struct/memory/main.go b/base/struct/memory/main.go new file mode 100644 index 0000000..6962778 --- /dev/null +++ b/base/struct/memory/main.go @@ -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) +} diff --git a/base/struct/receiver/main.go b/base/struct/receiver/main.go new file mode 100644 index 0000000..1979e93 --- /dev/null +++ b/base/struct/receiver/main.go @@ -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() +}