Go 分布式学习利器(9)-- Go语言 结构体的行为定义和实现
文章目錄
- 1. Go語(yǔ)言的結(jié)構(gòu)體 -- 數(shù)據(jù)成員的封裝
- 2. Go (函數(shù)成員)行為的定義和實(shí)現(xiàn)
1. Go語(yǔ)言的結(jié)構(gòu)體 – 數(shù)據(jù)成員的封裝
Go語(yǔ)言官方給的描述是 既是面向?qū)ο笳Z(yǔ)言,也不算面向?qū)ο笳Z(yǔ)言。
不是面向?qū)ο笳Z(yǔ)言 是因?yàn)?Go語(yǔ)言并不支持繼承操作,而且對(duì)象 這個(gè)概念在Go語(yǔ)言中比較弱化,并不像C++/Java中 是面向?qū)ο笳Z(yǔ)法的核心體現(xiàn)。
是面向?qū)ο笳Z(yǔ)言 是因?yàn)?Go有對(duì)象的概念,也支持基本的對(duì)象封裝(包括對(duì)數(shù)據(jù)成員和成員函數(shù)的封裝)
如下:
type Person struct {id stringname stringage int
}
實(shí)例化對(duì)象的過(guò)程如下:
obj := Person{"0", "zhang", 20} // 方法一
obj1 := Person{id:"1",name: "wang",age: 21} // 方法二
obj2 := new(Person) // 方法三
obj2.id = "2"
obj2.name = "li"
obj2.age = 22
其中通過(guò) new 運(yùn)算符返回的結(jié)果 是指針類型,即類似于&Person{},同時(shí)Go中使用指針訪問(wèn)元素的時(shí)候也是通過(guò).運(yùn)算符,而不像C/C++中的->運(yùn)算符
測(cè)試代碼如下:
type Person struct {id stringname stringage int
}func TestObject(t *testing.T) {obj := Person{"0", "zhang", 20}obj1 := Person{id:"1",name: "wang",age: 21}obj2 := new(Person)obj2.id = "2"obj2.name = "li"obj2.age = 22t.Log(obj)t.Log(obj1)t.Log(obj1.id)t.Log(obj2)t.Logf("obj is %T",obj) // 值類型t.Logf("obj1 is %T",obj1) // 值類型t.Logf("obj2 is %T", obj2) // 指針類型
}
最后的輸出如下
=== RUN TestObjectTestObject: oriented_test.go:19: {0 zhang 20}TestObject: oriented_test.go:20: {1 wang 21}TestObject: oriented_test.go:21: 1TestObject: oriented_test.go:23: &{2 li 22}TestObject: oriented_test.go:24: obj is Oriented_test.Person TestObject: oriented_test.go:25: obj1 is Oriented_test.PersonTestObject: oriented_test.go:26: obj2 is *Oriented_test.Person # 通過(guò)new 初始化的對(duì)象是指針類型
--- PASS: TestObject (0.00s)
2. Go (函數(shù)成員)行為的定義和實(shí)現(xiàn)
定義一個(gè)Person 結(jié)構(gòu)的行為(其他語(yǔ)言成為成員函數(shù))可以有如下兩種方式
- 結(jié)構(gòu)體對(duì)象的復(fù)制 定義
func (p Person) String() string { // 行為函數(shù)中傳入結(jié)構(gòu)體對(duì)象的 值return fmt.Println("id: %s-name: %s-age: %d\n", p.id,p.name,p.age) } - 避免內(nèi)存拷貝,結(jié)構(gòu)體對(duì)象的指針 定義
func (p *Person) String() string { // 行為函數(shù)中傳入結(jié)構(gòu)體對(duì)象的 指針return fmt.Println("id: %s-name: %s-age: %d\n", p.id,p.name,p.age) }
關(guān)于以上,僅僅 通過(guò)結(jié)構(gòu)體對(duì)象的指針來(lái)聲明成員函數(shù)即能夠避免一次內(nèi)存拷貝,這里我的理解是:
Go語(yǔ)言內(nèi)部的共享內(nèi)存機(jī)制,即像數(shù)組,map等結(jié)構(gòu) 是能夠通過(guò)指針來(lái)使用同一個(gè)內(nèi)存。同樣這里的成員函數(shù)的定義,本身創(chuàng)建好結(jié)構(gòu)的對(duì)象之后就可以使用同一個(gè)對(duì)象的內(nèi)存地址完成后續(xù)相關(guān)的定義,那么Go又原生支持指針這樣的操作,何必多此一舉再進(jìn)行一次內(nèi)存的分配、拷貝、釋放來(lái)降低語(yǔ)言本身的執(zhí)行效率。
測(cè)試函數(shù)如下:
type Person struct {id stringname stringage int
}func (p Person) String1() string{ // 多一次內(nèi)存拷貝的成員函數(shù)的實(shí)現(xiàn)fmt.Printf("String1 struct address is %x\n",unsafe.Pointer(&p.id))return fmt.Sprintf("id: %s-name: %s-age: %d\n", p.id,p.name,p.age)
}func (p *Person) String2() string{ // 能夠避免內(nèi)存拷貝的成員函數(shù)的實(shí)現(xiàn)fmt.Printf("String2 struct address is %x\n",unsafe.Pointer(&p.id))return fmt.Sprintf("id: %s-name: %s-age: %d\n", p.id,p.name,p.age)
}func TestObjectFun(t *testing.T) {obj := Person{"0", "zhang", 20}fmt.Printf("obj struct address is %x\n",unsafe.Pointer(&obj.id)) // 打印新對(duì)象的地址t.Log(obj.String1())t.Log(obj.String2())
}
輸出如下:
=== RUN TestObjectFun
obj struct address is c000090420
String1 struct address is c000090450TestObjectFun: oriented_test.go:46: id: 0-name: zhang-age: 20String2 struct address is c000090420 TestObjectFun: oriented_test.go:47: id: 0-name: zhang-age: 20--- PASS: TestObjectFun (0.00s)
通過(guò)以上輸出,可以看到通過(guò) 指針?lè)绞蕉x的成員函數(shù)String2,則擁有相同的對(duì)象地址,不需要像String1一樣進(jìn)行一次內(nèi)存拷貝。
總結(jié)
以上是生活随笔為你收集整理的Go 分布式学习利器(9)-- Go语言 结构体的行为定义和实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 什么是死飞车
- 下一篇: Go 分布式学习利器(10)-- Go语