GO在文档中强调了根本没有继承这一概念
1.屏蔽现象
一个简单的demo
package main
import (
"fmt"
)
var name = 11
func main(){
var name =10
{
var name = 9
fmt.Println(name)
}
fmt.Println(name)
}
结果很明显,输出9,10
根据对作用域的理解,程序实体的访问权限由代码块控制,变量也属于程序实体, 嵌套的代码块导致变量出现被屏蔽的现象。这称为变量的屏蔽现象
那函数呢?
package main
import (
"fmt"
)
type AnimalCategory struct {
kingdom string // 界。
phylum string // 门。
class string // 纲。
order string // 目。
family string // 科。
genus string // 属。
species string // 种。
}
func (ac AnimalCategory) String() string {
return fmt.Sprintf("hi%s%s%s%s%s%s%s",
ac.kingdom, ac.phylum, ac.class, ac.order,
ac.family, ac.genus, ac.species)
}
type Animal struct {
scientificName string // 学名。
AnimalCategory // 动物基本分类。这里嵌入其他结构体
}
func (a Animal) String() string {
return fmt.Sprintf("%s (category: %s)",
a.scientificName, a.AnimalCategory)
}
func main(){
category := AnimalCategory{species: "cat"}
fmt.Printf("The animal category: %s\n", category)
animal := Animal{
scientificName: "American Shorthair",
AnimalCategory: category,
}
fmt.Printf("The animal: %s\n", animal)
}
我们发现在执行 main函数中的打印函数时,虽执行了Animal结构体的String方法,但是Animal中的String方法执行a.AnimalCategory的字符串时,并没有执行
AnimalCategory结构体定义的string方法,也就是说出现了同名函数的遮蔽现象。(Animal 内嵌结构体 AnimalCategory )
也就是说,虽然AnimalCategory利用嵌入字段,但是同名的方法还是会被覆盖(内嵌结构体的同名方法不会被执行)。
通过这个例子也就明白了Go中并没有继承的概念,Go语言利用了嵌入字段的特性,使得“子类”能够坐享其成的使用“父类”(嵌入结构体)的一切,即使某些方法不合心意,还可以利用屏蔽特性进行“方法的重写”去调整优化
2.空结构体
空结构体不占用空间
package main
import (
"unsafe"
)
func main(){
var a = struct{}{}
var b = 1
fmt.Printf("%d,%d",unsafe.Sizeof(a),unsafe.Sizeof(b))
}
既然不占用内存,那么我们就可以把他当作是js的undefined的占位符(这里描述不准确,undefined为一个变量,大致类比一下)来使用,比如利用map和空结构体来实现set
package main
import (
"fmt"
)
type Set map[string]struct{}
func (set Set) Has(s string) bool{
_,ok := set[s]
return ok
}
func (set Set) Add(s string) {
if ok := set.Has(s);!ok{
set[s] = struct{}{}
}
}
func (set Set) Del(s string){
delete(set,s)
}
func main(){
set := Set{}
fmt.Println(set.Has("a"))
set.Add("a")
fmt.Println(set.Has("a"))
set.Del("a")
fmt.Println(set.Has("a"))
}
实现不发送数据的通道,仅通知子协程执行任务
func worker(ch chan struct{}) {
<-ch //协程阻塞,有struct时执行任务
// TODO
fmt.Println("do something")
close(ch)
}
func main() {
ch := make(chan struct{})
go worker(ch)
ch <- struct{}{}
}
实现仅包含方法的结构体 这里不再做赘述
网友评论