脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - GO语言结构体面向对象操作示例

GO语言结构体面向对象操作示例

2022-09-16 11:26Jeff的技术栈 Golang

这篇文章主要介绍了GO语言编程中结构体面向对象的操作示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪

匿名字段初始化

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main
import "fmt"
type Person struct {
    name string //名字
    sex  byte   //性别
    age  int    //年龄
}
type Student struct {
    Person //只有类型,没有名字,匿名字段,继承了Person的成员
    id     int
    addr   string
}  
func main() {
    //顺序初始化
    var s1 Student = Student{Person{"mike", 'm', 18}, 1, "bj"}
    fmt.Println("s1 = ", s1)
    //自动推导类型
    s2 := Student{Person{"mike", 'm', 18}, 1, "bj"}
    //fmt.Println("s2 = ", s2)
    //%+v, 显示更详细
    fmt.Printf("s2 = %+v\n", s2)
    //指定成员初始化,没有初始化的常用自动赋值为0
    s3 := Student{id: 1}
    fmt.Printf("s3 = %+v\n", s3)
    s4 := Student{Person: Person{name: "mike"}, id: 1}
    fmt.Printf("s4 = %+v\n", s4)
    //s5 := Student{"mike", 'm', 18, 1, "bj"} //err
}

成员的操作

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main
import "fmt"
type Person struct {
    name string //名字
    sex  byte   //性别, 字符类型
    age  int    //年龄
}
type Student struct {
    Person //只有类型,没有名字,匿名字段,继承了Person的成员
    id     int
    addr   string
}
func main() {
    s1 := Student{Person{"mike", 'm', 18}, 1, "bj"}
    s1.name = "yoyo"
    s1.sex = 'f'
    s1.age = 22
    s1.id = 666
    s1.addr = "sz"
    s1.Person = Person{"go", 'm', 18}
    fmt.Println(s1.name, s1.sex, s1.age, s1.id, s1.addr)
}

同名字段

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main
import "fmt"
type Person struct {
    name string //名字
    sex  byte   //性别, 字符类型
    age  int    //年龄
}
type Student struct {
    Person //只有类型,没有名字,匿名字段,继承了Person的成员
    id     int
    addr   string
    name   string //和Person同名了
}
func main() {
    //声明(定义一个变量)
    var s Student
    //默认规则(纠结原则),如果能在本作用域找到此成员,就操作此成员
    //                  如果没有找到,找到继承的字段
    s.name = "mike" //操作的是Student的name,还是Person的name?, 结论为Student的
    s.sex = 'm'
    s.age = 18
    s.addr = "bj"
    //显式调用
    s.Person.name = "yoyo" //Person的name
    fmt.Printf("s = %+v\n", s)
}

非结构体匿名字段

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main
import "fmt"
type mystr string //自定义类型,给一个类型改名
type Person struct {
    name string //名字
    sex  byte   //性别, 字符类型
    age  int    //年龄
}
type Student struct {
    Person //结构体匿名字段
    int    //基础类型的匿名字段
    mystr
}
func main() {
    s := Student{Person{"mike", 'm', 18}, 666, "hehehe"}
    fmt.Printf("s = %+v\n", s) //s = {Person:{name:mike sex:109 age:18} int:666 mystr:hehehe}
    s.Person = Person{"go", 'm', 22}
    fmt.Println(s.name, s.age, s.sex, s.int, s.mystr)  // go 22 109 666 hehehe
    fmt.Println(s.Person, s.int, s.mystr)  // {go 109 22} 666 hehehe
}

结构体指针类型匿名字段

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main
import "fmt"
type Person struct {
    name string //名字
    sex  byte   //性别, 字符类型
    age  int    //年龄
}
type Student struct {
    *Person //指针类型
    id      int
    addr    string
}
func main() {
    s1 := Student{&Person{"mike", 'm', 18}, 666, "bj"}
    fmt.Println(s1.name, s1.sex, s1.age, s1.id, s1.addr)
    //先定义变量
    var s2 Student
    s2.Person = new(Person) //分配空间
    s2.name = "yoyo"
    s2.sex = 'm'
    s2.age = 18
    s2.id = 222
    s2.addr = "sz"
    fmt.Println(s2.name, s2.sex, s2.age, s2.id, s2.addr)
}

面向过程和对象函数的区别

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main
import "fmt"
//实现2数相加
//面向过程
func Add01(a, b int) int {
    return a + b
}
//面向对象,方法:给某个类型绑定一个函数
type long int
//tmp叫接收者,接收者就是传递的一个参数
func (tmp long) Add02(other long) long {
    return tmp + other
}
func main() {
    //var result int
    //result = Add01(1, 1) //普通函数调用方式
    //fmt.Println("result = ", result)
    //定义一个变量
    var a long = 2
    //调用方法格式: 变量名.函数(所需参数)
    r := a.Add02(3)
    fmt.Println("r = ", r)
    //面向对象只是换了一种表现形式
}

为结构体类型添加方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main
import "fmt"
type Person struct {
    name string //名字
    sex  byte   //性别, 字符类型
    age  int    //年龄
}
//带有接收者的函数叫方法
func (tmp Person) PrintInfo() {
    fmt.Println("tmp = ", tmp)
}
//通过一个函数,给成员赋值
func (p *Person) SetInfo(n string, s byte, a int) {
    p.name = n
    p.sex = s
    p.age = a
}
func main() {
    //定义同时初始化
    p := Person{"mike", 'm', 18}
    p.PrintInfo()  //tmp =  {mike 109 18}
    //定义一个结构体变量
    var p2 Person
    (&p2).SetInfo("yoyo", 'f', 22)
    p2.PrintInfo() //tmp =  {yoyo 102 22}
}

指针变量方法集

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main
import "fmt"
type Person struct {
    name string //名字
    sex  byte   //性别, 字符类型
    age  int    //年龄
}
func (p Person) SetInfoValue() {
    fmt.Println("SetInfoValue")
}
func (p *Person) SetInfoPointer() {
    fmt.Println("SetInfoPointer")
}
func main() {
    //结构体变量是一个指针变量,它能够调用哪些方法,这些方法就是一个集合,简称方法集
    p := &Person{"mike", 'm', 18}
    p.SetInfoPointer() //func (p *Person) SetInfoPointer()
    (*p).SetInfoPointer() //把(*p)转换层p后再调用,等价于上面
    //内部做的转换, 先把指针p, 转成*p后再调用
    //(*p).SetInfoValue()  //SetInfoValue
    //p.SetInfoValue()  // SetInfoValue
}

普通变量方法集

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main
import "fmt"
type Person struct {
    name string //名字
    sex  byte   //性别, 字符类型
    age  int    //年龄
}
func (p Person) SetInfoValue() {
    fmt.Println("SetInfoValue")
}
func (p *Person) SetInfoPointer() {
    fmt.Println("SetInfoPointer")
}
func main() {
    p := Person{"mike", 'm', 18}
    p.SetInfoPointer() //func (p *Person) SetInfoPointer()
    //内部,先把p, 转为为&p再调用, (&p).SetInfoPointer()
    p.SetInfoValue()  //直接调用,内部不需要转
}

方法的继承

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main
import "fmt"
type Person struct {
    name string //名字
    sex  byte   //性别, 字符类型
    age  int    //年龄
}
//Person类型,实现了一个方法
func (tmp *Person) PrintInfo() {
    fmt.Printf("name=%s, sex=%c, age=%d\n", tmp.name, tmp.sex, tmp.age)
}
//有个学生,继承Person字段,成员和方法都继承了
type Student struct {
    Person //匿名字段
    id     int
    addr   string
}
func main() {
    s := Student{Person{"mike", 'm', 18}, 666, "bj"}
    s.PrintInfo()
}

方法的重写

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main
import "fmt"
type Person struct {
    name string //名字
    sex  byte   //性别, 字符类型
    age  int    //年龄
}
//Person类型,实现了一个方法
func (tmp *Person) PrintInfo() {
    fmt.Printf("name=%s, sex=%c, age=%d\n", tmp.name, tmp.sex, tmp.age)
}
//有个学生,继承Person字段,成员和方法都继承了
type Student struct {
    Person //匿名字段
    id     int
    addr   string
}
//Student也实现了一个方法,这个方法和Person方法同名,这种方法叫重写
func (tmp *Student) PrintInfo() {
    fmt.Println("Student: tmp = ", tmp)
}
func main() {
    s := Student{Person{"mike", 'm', 18}, 666, "bj"}
    //就近原则:先找本作用域的方法,找不到再用继承的方法
    s.PrintInfo() //到底调用的是Person, 还是Student, 结论是Student
    //显式调用继承的方法
    s.Person.PrintInfo()
}

方法值

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main
import "fmt"
type Person struct {
    name string //名字
    sex  byte   //性别, 字符类型
    age  int    //年龄
}
func (p Person) SetInfoValue() {
    fmt.Printf("SetInfoValue: %p, %v\n", &p, p)
}
func (p *Person) SetInfoPointer() {
    fmt.Printf("SetInfoPointer: %p, %v\n", p, p)
}
func main() {
    p := Person{"mike", 'm', 18}
    fmt.Printf("main: %p, %v\n", &p, p)
    //p.SetInfoPointer() //传统调用方式
    //保存方式入口地址
    pFunc := p.SetInfoPointer //这个就是方法值,调用函数时,无需再传递接收者,隐藏了接收者
    pFunc()                   //等价于 p.SetInfoPointer()
    vFunc := p.SetInfoValue
    vFunc() //等价于 p.SetInfoValue()
}

方法表达式

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main
import "fmt"
type Person struct {
    name string //名字
    sex  byte   //性别, 字符类型
    age  int    //年龄
}
func (p Person) SetInfoValue() {
    fmt.Printf("SetInfoValue: %p, %v\n", &p, p)
}
func (p *Person) SetInfoPointer() {
    fmt.Printf("SetInfoPointer: %p, %v\n", p, p)
}
func main() {
    p := Person{"mike", 'm', 18}
    fmt.Printf("main: %p, %v\n", &p, p)
    //方法值   f := p.SetInfoPointer //隐藏了接收者
    //方法表达式
    f := (*Person).SetInfoPointer
    f(&p) //显式把接收者传递过去 ====》 p.SetInfoPointer()
    f2 := (Person).SetInfoValue
    f2(p) //显式把接收者传递过去 ====》 p.SetInfoValue()
}

以上就是GO语言结构体面向对象操作示例的详细内容,更多关于GO语言结构体面向对象的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/guyouyin123/p/13957774.html

延伸 · 阅读

精彩推荐
  • GolangGo逃逸分析示例详解

    Go逃逸分析示例详解

    这篇文章主要为大家介绍了Go逃逸分析示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...

    王中阳Go4632022-08-16
  • GolangGo中Channel发送和接收操作指南

    Go中Channel发送和接收操作指南

    在golang中channel属于较为核心的一个功能,尤其在go协程中,channel功能尤为重要,下面这篇文章主要给大家介绍了关于Go中Channel发送和接收操作的相关资料,需要...

    呦呦鹿鸣11112021-09-16
  • GolangGolang Printf,Sprintf,Fprintf 格式化详解

    Golang Printf,Sprintf,Fprintf 格式化详解

    这篇文章主要介绍了Golang Printf,Sprintf,Fprintf 格式化详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    小豆角8812021-04-19
  • Golang在 Golang 中使用 Cobra 创建 CLI 应用

    在 Golang 中使用 Cobra 创建 CLI 应用

    这篇文章主要介绍了在 Golang 中使用 Cobra 创建 CLI 应用,来看下 Cobra 的使用,这里我们使用的 go1.13.3 版本,使用 Go Modules 来进行包管理,需要的朋友可以参考...

    吱吱吱 (piperck) XD4962022-01-26
  • Golanggolang使用 gomodule 在公共测试环境管理go的依赖的实例详解

    golang使用 gomodule 在公共测试环境管理go的依赖的实例详解

    这篇文章主要介绍了golang使用 gomodule 在公共测试环境管理go的依赖,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友...

    xiaoliizi4552021-02-05
  • Golanggolang API开发过程的中的自动重启方式(基于gin框架)

    golang API开发过程的中的自动重启方式(基于gin框架)

    这篇文章主要介绍了golang API开发过程的中的自动重启方式(基于gin框架),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的...

    千里之行,始于足下12312021-02-25
  • Golang使用 Go 管理版本的方法示例

    使用 Go 管理版本的方法示例

    这篇文章主要介绍了使用 Go 管理版本的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面...

    帅气猫咪3982020-05-29
  • Golang详解go语言的并发

    详解go语言的并发

    这篇文章主要介绍了go语言并发的相关资料,帮助大家更好的理解和学习使用golang,感兴趣的朋友可以了解下...

    bainianminguo9872021-04-18