Skip to content

结构体

type Person struct {
Name string
Age int
}
// 使用var声明结构体变量,默认值是零值
var p Person
// 使用结构体字面量
p := Person{
Name: "张三",
Age: 18,
}
// 使用new函数,返回指针
func NewPerson(name string, age int) *Person {
return &Person{
Name: name,
Age: age,
}
}
// 访问结构体成员
fmt.Println(p.Name)
package main
import "fmt"
type User struct {
name string
age int
}
type News struct {
title string
}
func (n News) Report() {
fmt.Printf("report %s\n", n.title)
}
type fakeNews = News
func main() {
var n1 = fakeNews{
title: "fakeNews",
}
n1.Report()
// 初始化结构体
// Go 没有构造函数,需要手动初始化
u1 := &User{} // u1是*User类型
u2 := User{} // u2是User类型
u3 := new(User) // u3是*User类型,Go会为其分配内存,并填充零值,然后返回其地址
var u4 User // u是User类型
var u5 *User // u5是*User类型,未分配内存,值为nil,调用方法会panic
// 字段赋值
u6 := User{ // u6是User类型,并且初始化了name和age
name: "Tom",
age: 10,
}
u7 := User{} // u7是User类型,后面再赋值
u7.name = "Tom"
u7.age = 10
fmt.Printf("u1: %v\n", u1) // u1: &{ 0}
fmt.Printf("u2: %v\n", u2) // u2: { 0}
fmt.Printf("u3: %v\n", u3) // u3: &{ 0}
fmt.Printf("u4: %v\n", u4) // u4: { 0}
fmt.Printf("u5: %v\n", u5) // u5: <nil>
fmt.Printf("u6: %v\n", u6) // u6: {Tom 10}
fmt.Printf("u7: %v\n", u7) // u7: {Tom 10}
}
package main
import "fmt"
// 不定参数
type Profile struct {
// Id Name 是必须的
Id int
Name string
Address string
}
type Option func(p *Profile)
func NewProfile(id int, name string, options ...Option) *Profile {
p := &Profile{
Id: id,
Name: name,
}
for _, option := range options {
option(p)
}
return p
}
func WithAddress(address string) Option {
return func(p *Profile) {
p.Address = address
}
}
func main() {
profile := NewProfile(1, "Tom", WithAddress("China"))
fmt.Println(profile) // &{1 Tom China}
}

语法

func (接收者 接收者类型) 方法名(参数列表)返回值列表 {
// 方法体
}

接收者类型:

  • 值接收者:操作结构体的副本,不会影响原始值
  • 指针接收者:操作结构体的指针,可以修改原始值
package main
import "fmt"
type BankAccount struct {
AccountNumber string // 账号
AccountHolder string // 账户持有人
Balance float64 // 账户余额
IsActive bool // 账户是否激活
}
func (ba BankAccount) GetAccountInfo() string {
status := "活跃"
if !ba.IsActive {
status = "冻结"
}
return fmt.Sprintf("Account Number: %s, Account Holder: %s, Balance: %.2f, IsActive: %s", ba.AccountNumber, ba.AccountHolder, ba.Balance, status)
}
// Deposit 存款
func (ba *BankAccount) Deposit(amount float64) error {
if !ba.IsActive {
return fmt.Errorf("账户已冻结")
}
if amount <= 0 {
return fmt.Errorf("存款金额必须大于0")
}
ba.Balance += amount
return nil
}
// Withdraw 取款
func (ba *BankAccount) Withdraw(amount float64) error {
if !ba.IsActive {
return fmt.Errorf("账户已冻结")
}
if amount <= 0 {
return fmt.Errorf("取款金额必须大于0")
}
if amount > ba.Balance {
return fmt.Errorf("余额不足")
}
ba.Balance -= amount
return nil
}
// 冻结账号
func (ba *BankAccount) Freeze() {
ba.IsActive = false
}
// 激活账号
func (ba *BankAccount) Activate() {
ba.IsActive = true
}
func main() {
account := BankAccount{
AccountNumber: "1234567890",
AccountHolder: "张三",
Balance: 1000.0,
IsActive: true,
}
fmt.Println(account.GetAccountInfo()) // Account Number: 1234567890, Account Holder: 张三, Balance: 1000.00, IsActive: 活跃
err := account.Deposit(500.0)
if err != nil {
fmt.Println(err)
}
fmt.Println(account.Balance) // 1500
err = account.Withdraw(200.0)
if err != nil {
fmt.Println(err)
}
fmt.Println(account.Balance) // 1300
account.Freeze()
err = account.Deposit(500.0)
if err != nil {
fmt.Println(err) // 账户已冻结
}
fmt.Println(account.Balance) // 1300
}
package main
import "fmt"
type rect struct {
width, height int
}
func (r *rect) area() int {
return r.width * r.height
}
func (r rect) perim() int {
return 2*r.width + 2*r.height
}
func main() {
r := rect{width: 10, height: 5}
fmt.Println("area: ", r.area()) // area: 50
fmt.Println("perim:", r.perim()) // perim: 30
// 修改结构体的值,要使用指针来调用方法
rp := &r
fmt.Println("area: ", rp.area()) // area: 50
fmt.Println("perim:", rp.perim()) // perim: 30
}
package main
import "fmt"
// 结构体
type Fish struct {
}
// 方法
func (f Fish) Swim() {
fmt.Println("I am swimming")
}
// 定义一个新类型
type FakeFish struct {
}
func (f FakeFish) FakeSwim() {
fmt.Println("I am swimming in the sky")
}
type SeaFish struct {
}
func (f SeaFish) Swim() {
fmt.Println("I am swimming in the sea")
}
func main() {
fake := FakeFish{}
//fake.Swim() // 编译错误,FakeFish 类型没有 Swim 方法
fake.FakeSwim() // I am swimming in the sky
// 类型转换,转换后可以使用 Fish 类型的方法
tk := Fish(fake)
tk.Swim() // I am swimming
sf := SeaFish{}
// 这里调用的是 SeaFish 的 Swim 方法
sf.Swim() // I am swimming in the sea
tk = Fish(sf)
// 这里调用的是 Fish 的 Swim 方法
tk.Swim() // I am swimming
}