【Go结构体和方法】

结构体和方法

结构

  • 结构把有内在联系的不同类型的数据统一成一个整体,使它们相互关联
  • 结构是变量的集合,从外部看是一个实体
  • 结构支持嵌套
  • 结构的字段类型不限
  • 结构的存储空间连续,按声明时的顺序存放
    在这里插入图片描述

结构定义

  • 命名类型结构
  • 匿名类型结构
type Employee struct {
    firstName string
    lastName  string
    age       int
    salary    int
}
//等价于
type Employee struct {
    firstName, lastName string
    age, salary         int
}
//匿名类型结构
var myemployee struct {  
    firstName, lastName string
    age, salary         int
}
//带标签(tag)的结构体
//用来描述字段的信息
type User struct {
    UserName string "用户名称"
    UserId   int    `json:"user_id" bson:"b_user_id"`
}

结构变量初始化

用命名类型结构或匿名类型结构声明的结构变量,各字段初始化为相关类型的零值
用字段名初始化,不用按顺序,未指定的字段为零值
用字面量初始化,按字段类型声明顺序并全部设置,顺序不对或遗漏字段报错

emp1 := Employee{
    firstName: "Sam",
    age:       25,
    salary:    500,
    lastName:  “Anderson”, //逗号不能忽略
}
//报错
emp2 := Employee{"Thomas", "Paul", 29, 800}

访问和修改结构变量的各个字段

//采用 结构变量.字段
    emp := Employee{"Thomas", "Paul", 29, 800}
    fmt.Println(emp.age)
//采用(*结构变量指针).字段
    emp := &Employee{"Sam", "Anderson", 55, 6000}
    fmt.Println("First Name:", (*emp).firstName)
//采用 结构变量指针.字段,不支持->
    emp := &Employee{"Sam", "Anderson", 55, 6000}
    fmt.Println("First Name:", emp.firstName)
//匿名字段
    type Person struct {
        string
        int
    }
    p := Person{"Naveen", 50}
    p.int =60
//匿名字段
//结构体字段也可以省略字段名,字段名默认为对应数据类型名称(数据类型不能重复)
    type Person struct {
        string
        int
    }
    p := Person{"Naveen", 50}
    p.int =60

嵌套字段和子结构字段提升

子结构字段提升(没有同名父结构字段)

type Address struct {
    city, state string
}
type Person struct {
    name    string
    age     int
    address Address
}
func main() {
    var p Person
    p.name = "Naveen"
    p.age = 50
    p.address = Address{
        city:  "Chicago",
        state: "Illinois",
    }
    fmt.Println("Name:", p.name)
    fmt.Println("Age:", p.age)
    fmt.Println("City:", p.address.city)
    fmt.Println("State:", p.address.state)
}
//子结构字段提升(没有同名父结构字段)
type Address struct {  
    city, state string
}
type Person struct {  
    name string
    age  int
    Address  //子结构匿名
}
func main() {  
    var p Person
    p.name = "Naveen"
    p.age = 50
    p.Address = Address{
        city:  "Chicago",
        state: "Illinois",
    }
    fmt.Println("Name:", p.name)
    fmt.Println("Age:", p.age)
    fmt.Println(“City:, p.city) //city 提升
    fmt.Println(“State:, p.state) //state 提升
}

方法

  • 方法是对具体类型行为的封装,本质上是绑定到该类型的函数
  • 非命名类型不能定义方法
  • OO语言的方法通常有个隐藏的this或self指针来指向对象
  • GO 把这个隐藏指针暴露出来,称为接收者(receiver)
  • 接收者可自定义名称,语法格式:
    • 值类型 func (t Type) funcName(paramList)(resultList)
    • 指针func (t *Type) funcName(paramList)(resultList)
type Employee struct {
    name     string
    salary   int
    currency string
}
//定义方法
func (e Employee) displaySalary() {
    fmt.Printf("Salary of %s is %s%d", e.name, e.currency, e.salary)
}
func main() {
    emp1 := Employee{
        name:     "Sam Adolf",
        salary:   5000,
        currency: "$",
    }
    emp1.displaySalary() 
}
//方法可用等价函数实现
type Employee struct {  
    name     string
    salary   int
    currency string
}
func displaySalary(e Employee) {  
    fmt.Printf("Salary of %s is %s%d", e.name, e.currency, e.salary)
}
func main() {  
    emp1 := Employee{
        name:     "Sam Adolf",
        salary:   5000,
        currency: "$",
    }
    displaySalary(emp1)
}

why?方法可用等价函数实现,为什么还要方法

  • GO 的函数不能重载,导致不同类型不能用同名函数,而不同类型的方法可以同名
  • GO 不支持class,使用结构代替类,结构字段用来封装对象属性,方法用来封装对象的行为

方法接收者(重要)

  • 方法接收者的本质是形参
    • 方法接收者为值时,方法修改对象属性将不能成功
    • 方法接收者为值时,需要在内存复制一份对象,效率低
package main

import "fmt"

type MyStruct struct {
	a int
	b int
	c int
}

func (item MyStruct) add() {
	item.c = item.a + item.b
}

func (itemPoint *MyStruct) p_add() {
	itemPoint.c = itemPoint.a + itemPoint.b
}

func main() {
	item := MyStruct{1, 1, 0}
	item.add()
	fmt.Printf("a={%v},b={%v},c={%v}\n", item.a, item.b, item.c)//a={1},b={1},c={0}
	item.p_add()
	fmt.Printf("a={%v},b={%v},c={%v}\n", item.a, item.b, item.c)//a={1},b={1},c={2}
}

方法提升

匿名子结构的方法可以像父结构方法一样被使用(没有同名父结构方法)

自定义类型扩展方法

方法并非结构体专有,所有自定义类型都可以定义方法

type myInt int //自定义类型

func (a *myInt) add(b myInt) myInt {
    return *a + b
}

num1 := myInt(5)
num2 := myInt(10)
sum := num1.add(num2)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值